Reversing orders of arrays/strings/lists

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
just me
Posts: 9576
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Reversing orders of arrays/strings/lists

05 Aug 2014, 02:07

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.
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).
In this case of in-place conversion I'd prefer "Ptr".
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: Reversing orders of arrays/strings/lists

05 Aug 2014, 02:15

thx just me
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
User avatar
nnnik
Posts: 4500
Joined: 30 Sep 2013, 01:01
Location: Germany

Re: Reversing orders of arrays/strings/lists

05 Aug 2014, 03:55

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.
Recommends AHK Studio
User avatar
LinearSpoon
Posts: 156
Joined: 29 Sep 2013, 22:55

Re: Reversing orders of arrays/strings/lists

05 Aug 2014, 05:24

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

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
}
The timer is QPC based. Times are ss:ms, and the percents are based off the longest time.
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%
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%
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.

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.
just me
Posts: 9576
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Reversing orders of arrays/strings/lists

05 Aug 2014, 09:39

@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.
just me
Posts: 9576
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Reversing orders of arrays/strings/lists

05 Aug 2014, 10:21

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"?
User avatar
LinearSpoon
Posts: 156
Joined: 29 Sep 2013, 22:55

Re: Reversing orders of arrays/strings/lists

05 Aug 2014, 17:14

@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.
lexikos
Posts: 9690
Joined: 30 Sep 2013, 04:07
Contact:

Re: Reversing orders of arrays/strings/lists

06 Aug 2014, 02:44

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
Does that answer the question?

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.
lexikos
Posts: 9690
Joined: 30 Sep 2013, 04:07
Contact:

Re: Reversing orders of arrays/strings/lists

06 Aug 2014, 03:51

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

Fixing it for address-of is a simple matter of adding case SYM_ADDRESS: in the appropriate switch statement. I will do this.
just me
Posts: 9576
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: Reversing orders of arrays/strings/lists

06 Aug 2014, 04:03

Thanks!

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 263 guests