Archive: How to speed this up?


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.

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
>

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:


If you want something fast, simply call SetEndOfFile using the System plug-in or your own plug-in.


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.)

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:

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.


To use SetEndOfFile:

CreateFile
SetFilePointer
SetEndOfFile
CloseHandle

Will work instantly


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


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?


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


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
>