以下统一示例为:采用递归方式计算斐波那契数列

AHK原版递归循环效果:8.25秒

C++ 源码 转 机器码MCode后:31毫秒

 

在线编译器:https://godbolt.org/           推荐的参数:FAcs /Og O2

 

V1原版递归测试+说明.ahk

; 对于过大的数据/字符串操作处理、计算密集型任务等,AHK的处理效率较慢
; 处理操作KB文件,AHK速度可能还行。但是,MB的文件,AHK会很慢
; 我认为这是因为我们基本上一点一点地更改了几千位,而在我的脚本中,我们只复制并使用不区分大小写的比较。
; 这与 BubbleSort【冒泡排序】 比 SelectionSort【选择排序】 慢的原因相同,尽管在比较中同样复杂。

; js是jit编译的。该函数将在第100次迭代后被优化处理,之后将比较解释语言的速度与编译语言的速度。尾递归优化?

; AHK没有尾递归优化,所以递归效率很低很低
; ahk函数调用的成本非常高,尤其是递归调用

; 想ahk快点可以像汇编一样用label跳来跳去【V1用标签跳转不保留栈的,Goto跳转后local环境直接没了】
; 栈是干什么的? 栈是:保留跳转前的环境信息
; 20240204测试:刚才试了一下,现在版本的v1应该是都可以保留了【1.1.37.00开始v1有重构过代码】
; 我第一次开始写debug插件,看scite4ahk的debug部分的代码的时候。那时候发现,在Goto跳转之后,debuger获取不到local的变量

SetBatchLines -1

fn(n) {
    if n < 2
        return n
    return fn(n - 1) + fn(n - 2)
}
t := A_TickCount
MsgBox % fn(35) "`n耗时:" (A_TickCount - t)/1000 " 秒"

 

V1转机器码MCode测试.ahk

; https://github.com/joedf/MCode4GCC
; https://www.autohotkey.com/boards/viewtopic.php?f=7&t=32
; https://www.autohotkey.com/boards/viewtopic.php?f=6&t=4642
/*  C++ 源码【采用递归方式计算斐波那契数列】
int fn(int n) {
   if (n < 2)
        return n;
   return fn(n - 1) + fn(n - 2);
}
*/

SetBatchLines -1

t1:=A_TickCount
MyFunction := MCode("2,x64:VVdWU0iD7CiD+QGJyH4pjWn+MduNef2J6I1x/4Pg/inHifGD7gLo1f///wHDOf518IPlAY1EHQBIg8QoW15fXcM=")
MsgBox % DllCall(MyFunction, "int", 35,"cdecl") "`n耗时:" A_TickCount-t1 " 毫秒"
Return

MCode(mcode) {
  static e := {1:4, 2:1}, c := (A_PtrSize=8) ? "x64" : "x86"
  if (!regexmatch(mcode, "^([0-9]+),(" c ":|.*?," c ":)([^,]+)", m))
    return
  if (!DllCall("crypt32\CryptStringToBinary", "str", m3, "uint", 0, "uint", e[m1], "ptr", 0, "uint*", s, "ptr", 0, "ptr", 0))
    return
  p := DllCall("GlobalAlloc", "uint", 0, "ptr", s, "ptr")
  if (c="x64")
    DllCall("VirtualProtect", "ptr", p, "ptr", s, "uint", 0x40, "uint*", op)
  if (DllCall("crypt32\CryptStringToBinary", "str", m3, "uint", 0, "uint", e[m1], "ptr", p, "uint*", s, "ptr", 0, "ptr", 0))
    return p
  DllCall("GlobalFree", "ptr", p)
}

 

V2原版递归测试.ahk2

#Requires AutoHotkey v2.0
#MaxThreads 255
ListLines False
KeyHistory 0

fn(n) {
    if n < 2
        return n
    return fn(n - 1) + fn(n - 2)
}

t := A_TickCount
MsgBox fn(35) "`n耗时:" (A_TickCount - t)/1000 " 秒"

 

V2转机器码MCode测试.ahk2

#Requires AutoHotkey v2.0
/*  C++ 源码【采用递归方式计算斐波那契数列】
int fn(int n) {
   if (n < 2)
        return n;
   return fn(n - 1) + fn(n - 2);
}
*/

t1:=A_TickCount
MyFunction := MCode("2,x64:VVdWU0iD7CiD+QGJyH4pjWn+MduNef2J6I1x/4Pg/inHifGD7gLo1f///wHDOf518IPlAY1EHQBIg8QoW15fXcM=")
MsgBox MyFunction("int",35,"cdecl") "`n耗时:" A_TickCount-t1 " 毫秒"
Return

MCode(hex, argtypes := 0, &code := 0) {
  static reg := "^([12]?).*" (c := A_PtrSize = 8 ? "x64" : "x86") ":([A-Za-z\d+/=]+)"
  if (RegExMatch(hex, reg, &m))
    hex := m[2], flag := m[1] = "1" ? 4 : m[1] = "2" ? 1 : hex ~= "[+/=]" ? 1 : 4
  else
    flag := hex ~= "[+/=]" ? 1 : 4
  if (!DllCall("crypt32\CryptStringToBinary", "str", hex, "uint", 0, "uint", flag, "ptr", 0, "uint*", &s := 0, "ptr", 0, "ptr", 0))
    return
  code := Buffer(s)
  if (DllCall("crypt32\CryptStringToBinary", "str", hex, "uint", 0, "uint", flag, "ptr", code, "uint*", &s, "ptr", 0, "ptr", 0) && DllCall("VirtualProtect", "ptr", code, "uint", s, "uint", 0x40, "uint*", 0)) {
    args := []
    if (Type(argtypes) = "Array" && argtypes.Length) {
      args.Length := argtypes.Length * 2 - 1
      for i, t in argtypes
        args[i * 2 - 1] := t
    }
    return DllCall.Bind(code, args*)
  }
}

 

声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。