In this case of in-place conversion I'd prefer "Ptr".Performance
Finally, when passing a string-variable to a function that will not change the length of the string, performance is improved by passing the variable by address (e.g. &MyVar) rather than as a "str" (especially when the string is very long). The following example converts a string to uppercase: DllCall("CharUpper", Ptr, &MyVar, Ptr).
Reversing orders of arrays/strings/lists
Re: Reversing orders of arrays/strings/lists
If the type is "Str", a temporary copy of the original string is passed to the function and the result has to be moved back into the variable.
Re: Reversing orders of arrays/strings/lists
thx just me
so the correct way is this:
so the correct way is this:
Code: Select all
loop 200
string .= "1234567890"
MsgBox % "StrLen: " StrLen(string) "`n" StringReverse(string)
StringReverse(str)
{
static rev := A_IsUnicode ? "_wcsrev" : "_strrev"
DllCall("msvcrt.dll\" rev, "Ptr", &str) ; "CDECL"
return str
}
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
Re: Reversing orders of arrays/strings/lists
They are exactly the same in the case that str contains a str.
But it is also possible that str contains a number for example.
In that case I'd prefer the first one.
However the uint version will crash in AHK_64.
But it is also possible that str contains a number for example.
In that case I'd prefer the first one.
However the uint version will crash in AHK_64.
Recommends AHK Studio
- LinearSpoon
- Posts: 156
- Joined: 29 Sep 2013, 22:55
Re: Reversing orders of arrays/strings/lists
@jNizM:
1. These functions are defined to need cdecl, although they still seems to work without specifying it.
2. The function can be further improved by preloading the function address with GetProcAddress. Autohotkey normally does this for you before the script starts, but in this case the function name isn't known until runtime.
3. I am consistently finding that str is faster than ptr, in this case. My MCodeStrReverse from the first page improved when passing output as ptr, but got worse when passing input as ptr. Even after browsing the source code, I am not sure how to explain the difference.
@just me: The manual also says this.
The timer is QPC based. Times are ss:ms, and the percents are based off the longest time.
At this point I somewhat lost interest. Very few scripts will need to reverse hundreds of thousands of strings composed of thousands of characters, and the difference is only a fraction of a second no matter which option you take.
1. These functions are defined to need cdecl, although they still seems to work without specifying it.
2. The function can be further improved by preloading the function address with GetProcAddress. Autohotkey normally does this for you before the script starts, but in this case the function name isn't known until runtime.
3. I am consistently finding that str is faster than ptr, in this case. My MCodeStrReverse from the first page improved when passing output as ptr, but got worse when passing input as ptr. Even after browsing the source code, I am not sure how to explain the difference.
@just me: The manual also says this.
These are the functions as I tested them, and sample results for each AHK version. Each input string was 2500 characters tested 100000 times for each function.Script Compatibility wrote:If "Str" or the equivalent type for the current build is used as a parameter, the address of the string or var is passed to the function, otherwise a temporary copy of the string is created in the desired format and passed instead.
Code: Select all
StringReverse(str)
{
static rev := A_IsUnicode ? "_wcsrev" : "_strrev"
DllCall("msvcrt.dll\" rev, "ptr", &str, "cdecl") ; "ptr type"
return str
}
StringReverse2(str)
{
static rev := A_IsUnicode ? "_wcsrev" : "_strrev"
DllCall("msvcrt.dll\" rev, "str", str, "cdecl") ; "str type"
return str
}
StringReverse3(str)
{
static pRev := DllCall("GetProcAddress", "ptr", DllCall("LoadLibrary", "Str", "msvcrt.dll", "ptr"), "aStr", A_IsUnicode ? "_wcsrev" : "_strrev", "ptr")
DllCall(pRev, "str", str, "cdecl") ;func address preloaded
return str
}
MCodeStrReverse(byref input)
{
static reverse
if (!reverse)
{
if A_IsUnicode
reverse := MCode("
(LTrim Join
1,x86:8b4c240c568b742408498d0c4e3bce721c8b54240c668b018d520283e902668942fe3bce73ef33c06689025ec38b44
240c33c95e668908c3,x64:418bc048ffc8488d0441483bc1721790440fb7004883e802488d520266448942fe483bc173ea3
3c0668902c3
)")
else
reverse := MCode("
(LTrim Join
1,x86:8b44240c48568b74240803c63bc672168b54240c8a088d520148884aff3bc673f3c602005ec38b44240c5ec60000c3
)")
}
VarSetCapacity(output, 2*strlen(input))
DllCall(reverse, "str", input, "ptr", &output, "uint", strlen(input), "Cdecl") ;Changed output to ptr type, speed is reduced if input is ptr type
return output
}
AHK 32 bit ANSI wrote: StringReverse: 00:804 100.00%
StringReverse2: 00:651 80.97%
StringReverse3: 00:545 67.79%
MCodeStrReverse: 00:464 57.71%
AHK 32 bit Unicode wrote: StringReverse: 00:737 100.00%
StringReverse2: 00:604 81.95%
StringReverse3: 00:519 70.42%
MCodeStrReverse: 00:470 63.77%
MCodeStrReverse has a small advantage over the others in that it is passed the string length (which AHK caches). _wcsrev and _strrev must find the null terminator on their own before reversing anything. jNizM function has the advantage of simplicity and size though.AHK 64 bit Unicode wrote: StringReverse: 00:853 100.00%
StringReverse2: 00:727 85.23%
StringReverse3: 00:643 75.38%
MCodeStrReverse: 00:606 71.04%
At this point I somewhat lost interest. Very few scripts will need to reverse hundreds of thousands of strings composed of thousands of characters, and the difference is only a fraction of a second no matter which option you take.
Re: Reversing orders of arrays/strings/lists
@LinearSpoon:
I confirm your results. But I don't understand what happens. According to the docs (Scipt Compatibility & DllCall) both DllCalls are passing a pointer, so what is causing a time difference up to more than 30 % for strings longer than 2048 characters on U64?
Seems to be a question for lexikos.
I confirm your results. But I don't understand what happens. According to the docs (Scipt Compatibility & DllCall) both DllCalls are passing a pointer, so what is causing a time difference up to more than 30 % for strings longer than 2048 characters on U64?
Seems to be a question for lexikos.
Re: Reversing orders of arrays/strings/lists
You shouldn't do the same mistake twice. Years ago a found a performance problem when testing string concatenation. The reason was (as Chris stated) that I used pure numeric strings for testing, the same as I did now for the Dllcall test. Changing my test string to alphabetic characters solved the problem, now and then. Now my benchmark reports better performance for the DllCall using "Ptr" for strings longer than 512 characters.
Might be a bug in the "string parser"?
Might be a bug in the "string parser"?
- LinearSpoon
- Posts: 156
- Joined: 29 Sep 2013, 22:55
Re: Reversing orders of arrays/strings/lists
@just me
I was originally using a pure numeric string for testing, although I hadn't considered the possibility that AHK would treat at it as a number, since it was a far larger number than AHK can hold/do math with.
Using an input string with no numbers makes ptr type improve performance in all cases.
I was originally using a pure numeric string for testing, although I hadn't considered the possibility that AHK would treat at it as a number, since it was a far larger number than AHK can hold/do math with.
Using an input string with no numbers makes ptr type improve performance in all cases.
Re: Reversing orders of arrays/strings/lists
Does that answer the question?Finally, when passing a string-variable to a function that will not change the length of the string, performance is improved by passing the variable by address (e.g. &MyVar) rather than as a "str" (especially when the string is very long).
Source: DllCall
You aren't really comparing the performance of Ptr vs Str, but of Ptr, &Var vs Str, Var. The extra & operation has a cost, but it is fixed overhead (edit: not entirely true - see below), whereas Str depends on the length of the string.
Re: Reversing orders of arrays/strings/lists
This was due to ExpandExpression (the function which evaluates post-compiled expressions) checking the numericness of each operand prior to performing the operation. Most of the operators need this information, but concat doesn't. Chris fixed it in v1.0.48.01 by skipping those checks for concat. (This is according to comments in the source code; the changelog doesn't mention it.)just me wrote:The reason was (as Chris stated) that I used pure numeric strings for testing, the same as I did now for the Dllcall test.
Fixing it for address-of is a simple matter of adding case SYM_ADDRESS: in the appropriate switch statement. I will do this.
Who is online
Users browsing this forum: No registered users and 263 guests