|
|
WorkBuddy
深度思考
老实说:单元素读写已经接近 EPL 的极限了
每次调用的开销拆解:
写整数_加速(索引, 值)
→ EPL 压栈/跳转(~10ns)
→ 写整数到地址 DLL IAT 跳转(~5ns)
→ RtlMoveMemory 内部(~5ns)
→ 实际写 4 字节(~1ns)
真正干活的只有最后 1ns,前面 20ns 都是调用开销。 EPL 的函数调用机制你改不了。
三条路,收益递减
路线1:批量操作(已实现,最实用)
热循环里不要逐个读,拷贝到原生数组再遍历。前面已经做过了,78ms → 47ms。
路线2:写个 C DLL 做热循环
把整个循环搬进 C 里,EPL 只调一次:
c
复制
// fastlib.c → 编译成 fastlib.dll
__declspec(dllexport) int __cdecl SumArray(int* base, int count) {
int sum = 0;
for (int i = 0; i < count; i++) {
sum += base[i]; // 编译成单条 MOV 指令
}
return sum;
}
EPL 调用:
epl
复制
.DLL命令 求和, 整数型, "fastlib.dll", "SumArray"
.参数 基址, 整数型, , , 内存数组基址
.参数 数量, 整数型, , , 元素个数
结果 = 求和 (ccc.取基址 (), ccc.取数组成员数目 ())
一次调用完成 100 万次累加,时间接近 0。 这才是真正消灭调用开销的办法。
路线3:EPL 置入代码(内联汇编)
EPL 支持 置入代码 写机器码,但极度脆弱,换个编译器版本可能就崩:
epl
复制
.子程序 写整数_极速, , 公开, 内联汇编版,不稳定慎用
.参数 参数_地址, 整数型 ' 直接传地址,不是索引
.参数 参数_值, 整数型
' mov eax, [ebp+12] ; 取值
' mov [ebp+8], eax ; 写入地址
' 不推荐,维护成本太高
置入代码 ({ 139, 69, 12, 139, 85, 8, 137, 2 })
不推荐用在正式项目里,调试困难,一崩就整个程序挂。
建议
方法 速度 可靠性 推荐度
拷贝到原生数组 快 ? 稳定 ??? 首选
C DLL 做热循环 最快 ? 稳定 ??? 高频场景必用
置入代码 理论最快 ? 脆弱 ? 不推荐
你的量化筛选如果真到了性能瓶颈,写个 C DLL 是正路。 几十行 C 代码就能把排序、累加、筛选全做了,EPL 只负责界面和流程控制。
龙虾对 读写瓶颈 这样说
|
|