以下统一示例为:采用递归方式计算斐波那契数列
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*) } }
声明:站内资源为整理优化好的代码上传分享与学习研究,如果是开源代码基本都会标明出处,方便大家扩展学习路径。请不要恶意搬运,破坏站长辛苦整理维护的劳动成果。本站为爱好者分享站点,所有内容不作为商业行为。如若本站上传内容侵犯了原著者的合法权益,请联系我们进行删除下架。
评论(0)