Author | Message | Time |
---|---|---|
Eli_1 | I was trying to make a program that would read a file, create a hex dump of it, and put it in a .txt file. I tested it on storm.dll, and it works... in 21 minutes... [code] Const FILE_READ As String = "C:\Program Files\Starcraft\storm.dll" Const FILE_DUMP As String = "C:\WINDOWS\DESKTOP\hexdump.txt" Const READ_SIZE As Long = 16 Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long) Private Declare Function GetTickCount Lib "kernel32" () As Long Dim startdump As Long Private Sub dumpfile(ByVal filename As String, ByVal outfile As String) Dim readcnt As Long Dim inbuf As String Dim tmpbuf As String Dim readtime As Double ' This is to figure out how long the ' whole proccess takes. startdump = GetTickCount Close #2 Open filename For Binary Access Read As #2 If LOF(2) = 0 Then Exit Sub pbar.Max = LOF(2) inbuf = Space$(LOF(2)) Get #2, , inbuf While LenB(inbuf) <> 0 tmpbuf = Left$(inbuf, 16) inbuf = Right$(inbuf, Len(inbuf) - 16) fappend hexdump(tmpbuf, readcnt), outfile readcnt = readcnt + 16 pbar.Value = readcnt Label1.Caption = readcnt & "/" & pbar.Max pbar.Refresh DoEvents Wend readtime = (GetTickCount - startdump) / 60000 Close #2 Label2.Caption = "Finished: ~" & readtime & " mins." End Sub Private Function hexdump(ByVal data As String, ByRef loffset As Long) As String Dim tmpbuf As String Dim spacebuf As String Dim perbuf As String Dim tmpoffset As String * 2 Dim offset As String spacebuf = Space$(16) perbuf = String(16, ".") CopyMemory ByVal tmpoffset, loffset, 2 tmphex = Hex(Asc(Mid$(tmpoffset, 2, 1))) offset = IIf(Val("&H" & tmphex) < 16, "0" & tmphex, tmphex) tmphex = Hex(Asc(Mid$(tmpoffset, 1, 1))) offset = IIf(Val("&H" & tmphex) < 16, offset & "0" & tmphex, offset & tmphex) tmpbuf = strtohex(data) For i = 1 To Len(data) If Asc(Mid$(data, i, 1)) <> 32 Then If Asc(Mid$(data, i, 1)) < 48 Or Asc(Mid$(data, i, 1)) > 122 Then Mid$(data, i, 1) = "." End If Next i hexdump = offset & ": " & tmpbuf & Left$(spacebuf, 16 - Len(data)) & " " & data & Left$(perbuf, 16 - Len(data)) End Function Private Function strtohex(ByVal data As String, Optional addspace As Byte = 0) As String Dim buffer As String Dim tmphex As String For i = 1 To Len(data) tmphex = Hex(Asc(Mid$(data, i, 1))) If Val("&H" & tmphex) < 16 Then tmphex = "0" & tmphex buffer = IIf(addspace = 0, buffer & tmphex & " ", buffer & tmphex) Next i strtohex = Left$(buffer, Len(buffer) - 1) End Function Private Sub fappend(ByVal data As String, ByVal filename As String) Close #1 Open filename For Append As #1 Print #1, data Close #1 End Sub Private Sub fclear(ByVal filename As String) Close #1 Open filename For Output As #1 Close #1 End Sub Private Sub Form_Activate() fclear FILE_DUMP dumpfile FILE_READ, FILE_DUMP End Sub [/code] Sample output: [quote]0000: 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 MZ.............. 0010: B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ........@....... 0020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0030: 00 00 00 00 00 00 00 00 00 00 00 00 E0 00 00 00 ................ 0040: 0E 1F BA 0E 00 B4 09 CD 21 B8 01 4C CD 21 54 68 ...........L..Th 0050: 69 73 20 70 72 6F 67 72 61 6D 20 63 61 6E 6E 6F is program canno 0060: 74 20 62 65 20 72 75 6E 20 69 6E 20 44 4F 53 20 t be run in DOS 0070: 6D 6F 64 65 2E 0D 0D 0A 24 00 00 00 00 00 00 00 mode............ 0080: 24 F7 6A E0 60 96 04 B3 60 96 04 B3 60 96 04 B3 ..j.`...`...`... 0090: 73 9E 59 B3 62 96 04 B3 60 96 05 B3 A2 96 04 B3 s.Y.b...`....... 00A0: E3 9E 59 B3 6B 96 04 B3 E3 8A 0A B3 64 96 04 B3 ..Y.k.......d... 00B0: 60 96 04 B3 43 96 04 B3 34 B5 35 B3 7C 96 04 B3 `...C...4.5..... 00C0: A7 90 02 B3 61 96 04 B3 9F B6 00 B3 61 96 04 B3 ....a.......a... 00D0: 52 69 63 68 60 96 04 B3 00 00 00 00 00 00 00 00 Rich`........... 00E0: 50 45 00 00 4C 01 06 00 A2 FB AB 40 00 00 00 00 PE..L......@.... . . . FFF0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ [/quote] Any idea why it takes so long (~21 minutes)? | June 13, 2004, 10:30 PM |
Adron | [quote author=Eli_1 link=board=31;threadid=7242;start=0#msg65077 date=1087165814] [code] .. inbuf = Right$(inbuf, Len(inbuf) - 16) .. [/code] [/quote] This is a very slow operation, because it will copy the entire file contents to a new buffer. It's makes the algorithm O(n^2). Reading the input file 16 bytes at a time would be faster, or using Mid to extract the data from inbuf. [quote author=Eli_1 link=board=31;threadid=7242;start=0#msg65077 date=1087165814] [code] ... pbar.Refresh DoEvents ... [/code] [/quote] This is slow, don't do it on every iteration. [quote author=Eli_1 link=board=31;threadid=7242;start=0#msg65077 date=1087165814] [code] Private Sub fappend(ByVal data As String, ByVal filename As String) Close #1 Open filename For Append As #1 Print #1, data Close #1 End Sub [/code] [/quote] Do you have On Error Resume Next? I don't see how the first Close succeeds. Opening and closing files is typically slow. Don't open and close files unnecessarily. | June 13, 2004, 11:41 PM |
Eli_1 | Thanks, Adron. I'll try some of your suggestions and get back to you. [quote] Reading the input file 16 bytes at a time would be faster ... [/quote] That was how the program was origionally designed. Both ways seem equally slow. | June 13, 2004, 11:52 PM |
Eli_1 | [quote] [code] .. inbuf = Right$(inbuf, Len(inbuf) - 16) .. [/code] This is a very slow operation, because it will copy the entire file contents to a new buffer. It's makes the algorithm O(n^2). Reading the input file 16 bytes at a time would be faster, or using Mid to extract the data from inbuf. [/quote] I'm using Mid to extract the data now (this made the huge difference). [quote] [code] ... pbar.Refresh DoEvents ... [/code] This is slow, don't do it on every iteration. [/quote] I now do it on every 100th iteration. The read/dump time on storm.dll is now ~1.59 minutes. This is a HUGE difference from the origional 21 minutes. I'm gonna try and only write to 'hexdump.txt' on every 100th iteration, along with the progressbar update - I'll post again if it makes a significant change. Thanks, Adron. | June 14, 2004, 12:06 AM |
Eli_1 | The main changes made are here: [code] ... While readcnt <> LOF(2) tmpbuf = Mid$(inbuf, readcnt + 1, 16) buffer = buffer & hexdump(tmpbuf, readcnt) & vbCrLf readcnt = readcnt + 16 If readcnt Mod (16 * 50) = 0 Or readcnt = LOF(2) Then pbar.Value = readcnt Label1.Caption = readcnt & "/" & pbar.Max pbar.Refresh fappend buffer, FILE_DUMP: buffer = vbNullString DoEvents End If Wend ... [/code] The new time is ~.8 minutes, but that's still a long time. How is it some of the hex editors like HexWorkshop seem to read a file and create identical output almost instantly? | June 14, 2004, 12:19 AM |
K | This may not make a big difference, but every function call has some overhead associated with it, and i'm not sure what exactly goes on inside LOF() -- it might be a very expensive function. Try storing the length of the file in a variable when the program first runs and using variable that in place of the LOF() calls. | June 14, 2004, 1:18 AM |
hismajesty | [quote author=Eli_1 link=board=31;threadid=7242;start=0#msg65077 date=1087165814] [code] Private Sub fappend(ByVal data As String, ByVal filename As String) Close #1 Open filename For Append As #1 Print #1, data Close #1 End Sub [/code] Do you have On Error Resume Next? I don't see how the first Close succeeds. Opening and closing files is typically slow. Don't open and close files unnecessarily. [/quote] That wouldn't cause an error and would execute fine but it's bad practice. He should should just do something like. [code]Dim fFile As Byte fFile = FreeFile 'Get unused file[/code] | June 14, 2004, 1:36 AM |
Eli_1 | [quote author=K link=board=31;threadid=7242;start=0#msg65101 date=1087175896] ... and i'm not sure what exactly goes on inside LOF() -- it might be a very expensive function. Try storing the length of the file in a variable when the program first runs and using variable that in place of the LOF() calls. [/quote] It did make a small difference. The time is at .7 minutes now. | June 14, 2004, 1:39 AM |
Adron | [quote author=Eli_1 link=board=31;threadid=7242;start=0#msg65093 date=1087172380] The new time is ~.8 minutes, but that's still a long time. How is it some of the hex editors like HexWorkshop seem to read a file and create identical output almost instantly? [/quote] Hex editors typically don't read the entire file. They throw up a window with a scrollbar large enough for the entire file (needs to check lof), and then read as much of the file as they need to display what you see (needs to read less than 1 kb). | June 14, 2004, 8:47 AM |
drivehappy | You may want to pass some of your larger variables in as ByRef so that it doesn't need to create a copy of one each time. You need to make sure that you don't change it in the function though. | June 14, 2004, 5:13 PM |
Eli_1 | [quote author=drivehappy link=board=31;threadid=7242;start=0#msg65211 date=1087233218] You may want to pass some of your larger variables in as ByRef so that it doesn't need to create a copy of one each time. You need to make sure that you don't change it in the function though. [/quote] [s]I'll try that in just a little bit.[/s] It didn't make a noticable difference. :( I got the time down to .4 minutes by using SetPriorityClass. | June 14, 2004, 6:26 PM |
Adron | [quote author=Eli_1 link=board=31;threadid=7242;start=0#msg65232 date=1087237579] I got the time down to .4 minutes by using SetPriorityClass. [/quote] SetPriorityClass is probably a bit the same as reducing the frequency of DoEvents calls. | June 14, 2004, 8:17 PM |