Code: Select all
t:=A_TickCount
Loop Parse, (1,String) ; around 10 times slower than: Loop Parse, String
continue
MsgBox A_TickCount-t
Code: Select all
t:=A_TickCount
Loop Parse, (1,String) ; around 10 times slower than: Loop Parse, String
continue
MsgBox A_TickCount-t
Code: Select all
DllCall('QueryPerformanceCounter', 'Int64*', start := 0)
Loop Parse, String
continue
DllCall('QueryPerformanceCounter', 'Int64*', end := 0)
MsgBox end - start ; 55-70
Code: Select all
DllCall('QueryPerformanceCounter', 'Int64*', start := 0)
Loop Parse, (1,String) ; around 10 times slower than: Loop Parse, String
continue
DllCall('QueryPerformanceCounter', 'Int64*', end := 0)
MsgBox end - start ; 60-75
Code: Select all
Loop Parse, String ; takes about 300 MSec for me
Loop Parse, (1,String) ; for same file takes about 6200 MSec for me
Code: Select all
t:=A_TickCount
Loop Parse, (i:=A_TickCount,String)
continue
MsgBox (A_TickCount-t) "`nstart:`t" t "`nloop:`t" i "`nnow:`t" A_TickCount
Was the second Loop Parse supposed to have the (1, String) part in this example?HotKeyIt wrote: ↑21 Jan 2020, 15:55For an around 12 MB file:This is 20 times slower.Code: Select all
Loop Parse, String ; takes about 300 MSec for me Loop Parse, String ; for same file takes about 6200 MSec for me
Code: Select all
t:=A_TickCount
Loop Parse, String . "TEST"
continue
MsgBox (A_TickCount-t) "`nstart:`t" t "`nloop:`t" i "`nnow:`t" A_TickCount
Code: Select all
; LARGE_DEREF_BUF_SIZE = 4 194 304
Loop Parse, ('' . 4_194_303_or_fewer_char_string) ; this is fine
continue
Loop Parse, ('a' . 4_194_303_char_string) ; lag
continue
Code: Select all
ResultType Line::ExpandArgs(ResultToken *aResultTokens)
...
// Always init our_buf_marker even if zero iterations, because we want to enforce
// the fact that its prior contents become invalid once we're called.
// It's also necessary due to the fact that all the old memory is discarded by
// the above if more space was needed to accommodate this line.
LPTSTR our_buf_marker = sDerefBuf; // Prior contents of buffer will be overwritten in any case.
Code: Select all
ResultType Line::PerformLoopParse(ResultToken *aResultToken, bool &aContinueMainLoop, Line *&aJumpToLine, Line *aUntil)
...
_tcscpy(buf, ARG1); // Make the copy.
// Make a copy of ARG2 and ARG3 in case either one's contents are in the deref buffer, which would
// probably be overwritten by the commands in the script loop's body:
TCHAR delimiters[512], omit_list[512];
tcslcpy(delimiters, ARG2, _countof(delimiters));
tcslcpy(omit_list, ARG3, _countof(omit_list));
// Free deref buffer otherwise each call to ExpandArgs will cause a slowdown by calling SET_DEREF_TIMER if sDerefBufSize > LARGE_DEREF_BUF_SIZE.
if (Line::sDerefBuf && Line::sDerefBufSize > LARGE_DEREF_BUF_SIZE)
{
free(Line::sDerefBuf);
--Line::sLargeDerefBufs;
SET_S_DEREF_BUF(NULL, 0);
}
Code: Select all
Loop 520188 ; create long string
s.="a"
; this Loop runs for around 30 Seconds when s is 510188 characters
; same Loop runs only for 3 seconds when s is 520187 characters
t:=A_TickCount
Loop 100000
if ("" s)
continue
MsgBox A_TickCount-t
If that's a problem, it is only because SET_DEREF_TIMER is more costly than expected, in which case that should be addressed separately. For instance, by using SetTimer() sparingly. If the timer was already set, record the "last use" time. When the timer elapses, evaluate whether enough time has passed; if not, calculate and reset the timer so that it will fire 10 seconds after the last use. SetTimer() would be called at most twice in a 10 second period, instead of potentially thousands of times.
The deref buf exists to be reused, to reduce the frequent reallocation of temporary memory blocks. By freeing it immediately, you are defeating the purpose. If a large deref buf is needed within the loop, a new one will be allocated, and the cost of SET_DEREF_TIMER will still be incurred repeatedly.I think to solve that, PerformLoopParse[CSV] will need to free the sDerefBuf right after copy of the content has been done: