- NSIS Discussion
- How to speed this up?
Archive: How to speed this up?
s793016
5th May 2004 06:42 UTC
How to speed this up?
Sorry, my English is very very poor.
For some reason, I must chop some file when install running.
so I write this script to do it, and it really work:
!macro Chop SrcID TarID BeginOff EndOff
push $1
push $2
push $3
IntOP $3 ${EndOff} + 0
FileSeek ${SrcID} 0 Cur $2
push $2
FileSeek ${SrcID} ${BeginOff}
IntOP $2 ${BeginOff} - 1
IntOP $2 $2 + 1
FileReadByte ${SrcID} $1
FileWriteByte ${TarID} $1
StrCmp $2 $3 0 -3
pop $2
FileSeek ${SrcID} $2
pop $3
pop $2
pop $1
!macroend
And my problem is: if I want to chop more than 64K (65535), the performance time for chop will become very slow.
I wished to do this chop by pure NSIS Script or NSIS Script + plugin.
Does anyone got any good idea?
Thank you very much.
deguix
5th May 2004 12:19 UTC
I did halfway I did in StrFunc.nsh, I transformed your macro into a function (less size) with simple call for only Install function.
To call the function use "${Chop} SrcID TarID BeginOff EndOff".
(I don't know if your function has a return, if it returns something, say what returns for me and I'll give another piece of code)
(The same thing applies if you use it in an Uninstaller, it it is for Install, Uninstall or both, say it to me and I'll do the complete implementation I did on StrFunc.nsh if necessary)
!define Chop "!insertmacro Chop"
>Function Chop
Exch $R3
Exch
Exch $R2
Exch
Exch 2
Exch $R1
Exch 2
Exch 3
Exch $R0
Exch 3
push$1
push$2
push$3
IntOP$3 ${EndOff} + 0
FileSeek${SrcID} 0 Cur $2
push$2
FileSeek${SrcID} ${BeginOff}
IntOP $2 ${BeginOff} - 1
IntOP$2 $2 + 1
FileReadByte${SrcID} $1
FileWriteByte${TarID} $1
StrCmp$2 $3 0 -3
pop$2
FileSeek${SrcID} $2
pop$3
pop$2
pop$1
Pop $R3
Pop $R2
Pop $R1
Pop $R0
FunctionEnd
>!macro Chop SrcID TarID BeginOff EndOff
Push${StcID}
Push ${TarID}
Push ${BeginOff}
Push ${EndOff}
Call Chop
>!macroend
>
s793016
5th May 2004 12:44 UTC
Thank you, deguix. ;)
This macro has no return.
I just use it for install phase right now, maybe somebody need it in other phase?
By the way, if you CHOP a piece longer than 60K bytes, the CHOP performance will become very slow.
I tried to CHOP for 64381 bytes before, and done it with 5 minutes ... :mad:
kichik
6th May 2004 18:02 UTC
If you want something fast, simply call SetEndOfFile using the System plug-in or your own plug-in.
deguix
7th May 2004 02:43 UTC
SetEndOfFile
The SetEndOfFile function moves the end-of-file (EOF) position for the specified file to the current position of the file pointer.
Input: Handle ($R0).
Output: Nothing.
NOTE: The file has to be opened in append or write mode.
System::Call "Kernel32.lib::SetEndOfFile(i)i(R0)"
(Not tested.)
s793016
7th May 2004 13:49 UTC
Fix something from deguix's function. This code is equal to above code.
"!insertmacro Chop"
>Function Chop
Exch $R3
Exch
Exch $R2
Exch
Exch 2
Exch $R1
Exch 2
Exch 3
Exch $R0
Exch 3
push$1
FileSeek $R0 0 Cur$1
push$1
FileSeek $R0 $R2
IntOP $R2 $R2- 1
IntOP $R2 $R2+ 1
FileReadByte $R0$1
FileWriteByte $R1$1
StrCmp $R2 $R3 0-3
pop$1
FileSeek $R0$1
pop$1
Pop $R3
Pop $R2
Pop $R1
Pop $R0
FunctionEnd
>!macro Chop SrcID TarID BeginOff EndOff
Push${SrcID}
Push ${TarID}
Push ${BeginOff}
Push ${EndOff}
Call Chop
>!macroend
>
And ... SetEndOfFile looks like no use ... :rolleyes:
deguix
7th May 2004 23:12 UTC
It is just an alternative way. This one uses the file current position to know to set the file end, and it cuts automatically every additional byte, or it adds bytes if not on this size.
And sorry for that of my code, it happens commonly.
brainsucker
4th June 2004 12:02 UTC
To use SetEndOfFile:
CreateFile
SetFilePointer
SetEndOfFile
CloseHandle
Will work instantly
brainsucker
4th June 2004 16:26 UTC
Full deguix's sample, 70000 - position to cut. Haven't tested it yet. But should work :)
FileOpen $1 "cutfile" "rw"
FileSeek $1 70000
System::Call "Kernel32::SetEndOfFile(i r1) i"
FileClose $1
s793016
5th June 2004 10:37 UTC
Sorry, my English is very very poor.
Why I said that SetEndOfFile API looks like no use?
Because we offen chop a file for just the middle part.
I make you an easy example. Assume those string is a file contains, looks like this:
"1234567890"
If we just need to get locate 4 ~ 9, we may insert a line like this:
${Chop} SrcID TarID 4 9
See? There is nothing left for SetEndOfFile API to do.
And the real problem is: Nometer SetEndOfFile do work or not, you still need to drop off 1 ~ 3 and cut off 4 ~ 9 by my slowest function itself.
... Maybe a Win32API for "Read File to Memory" and "Write Memory to File" could accerator this slowest function?
brainsucker
5th June 2004 17:44 UTC
Crops 'cutfile' to $3 bytes starting at $2 position.
FileOpen $1 "cutfile" "a"
FileSeek $1 $2
System::Alloc $3
System::Call "Kernel32::ReadFile(i r1, i sr4, i r3, *i 0 r5, i 0)"
FileSeek $1 0
System::Call "Kernel32::WriteFile(i r1, i r4, i r5, *i 0 r5, i 0)"
System::Call "Kernel32::SetEndOfFile(i r1) i"
FileClose $1
System::Free $4
s793016
6th June 2004 08:36 UTC
Great Work!!!:up: Big Thanks to brainsucker!:up: :up: :up:
And the merged new code is here:
"!insertmacro Chop"
>!macro Chop SrcID TarID BeginOff EndOff
Push${SrcID} ; -> $0
Push${TarID} ; -> $1
Push${BeginOff} ; -> $2
Push${EndOff} ; -> $3
Call Chop
>!macroend
>Function Chop
Exch$3 ; <- ${EndOff}
Exch
Exch$2 ; <- ${BeginOff}
Exch
Exch 2
Exch$1 ; <- ${TarID}
Exch 2
Exch 3
Exch$0 ; <- ${SrcID}
Exch 3
push$4
FileSeek$0 0 Cur $4
push$4
push$5
FileSeek$0 $2
IntOP$2 $3 - $2
IntOP$2 $2 + 1
StrCpy$3 ''
>System::Alloc $2
System
::Call "Kernel32::ReadFile(i r0, i sr5, i r2, *i 0 r3, i 0)"
>System::Call "Kernel32::WriteFile(i r1, i r5, i r3, *i 0 r3, i 0)"
>System::Free $5
pop$5
pop$4
FileSeek$0 $4
pop$4
Pop$3
Pop$2
Pop$1
Pop$0
FunctionEnd
>