Haxe CPP编译目标下Maps、Dynamic Object与固定对象性能对比问询
测试代码
var nd=()->{ //var op:Dynamic = {x:100,y:1000}; //op.z = 22; var op = {x:100,y:1000,z:22} //var op = ['x'=>100,'y'=>1000]; //op['z'] = 22; var i; for(i in 0...1000000) { /* op['x']++; op['y']--; op['z']++; */ op.x++; op.y--; op.z++; } trace('Line'); } var j; var q:Float = haxe.Timer.stamp(); for(j in 0...100) nd(); trace(haxe.Timer.stamp()-q);
测试运行结果:
- Maps:19秒
- Dynamic Object:9秒
- 固定对象:0.6秒
三者性能差距巨大的核心原因
- 固定对象:Haxe编译阶段就已经确定了它的所有字段结构,字段访问会被直接编译为固定偏移量的内存寻址操作,没有任何运行时查找开销,还能享受编译器的循环优化、内联优化等,所以性能最高。
- Dynamic Object:属于动态类型的字符串键哈希表,Haxe底层和各编译目标平台都对动态对象的属性访问做了轻量优化,仅需要做一次简单的字符串哈希查找即可完成读写,没有额外的类型校验开销,所以性能居中。
- Map:是支持任意类型键的通用键值集合,为了兼容所有合法键类型,每一次读写都要完成键哈希计算、哈希冲突处理、键相等性校验三个步骤,同时Map的读写方法是虚函数调用,也没有针对字符串键做特殊捷径优化,所以额外开销最大,性能最低。
实际开发中的选择规则
- 优先选择固定对象/自定义类实例:只要提前能确定需要用到的字段名、字段类型,就优先用这种结构,既可以获得编译期类型安全检查,又能拿到最高的运行性能,能覆盖绝大多数常规开发场景。
- 仅在需要动态增删字符串键时用Dynamic Object:如果键固定为字符串类型,且无法提前确定所有键名、需要运行时动态增删键的时候再使用,注意它会丢失编译期类型检查,不要随意滥用。
- 仅在非字符串键/需要通用集合能力时用Map:如果你的键不是字符串类型(比如数字、枚举、自定义类实例),或者需要用到Map内置的遍历键值对、判断键存在、批量操作等集合API的时候再使用,不要用Map实现纯字符串键的键值存储,会带来不必要的性能损耗。
内容的提问来源于stack exchange,提问作者Nertan Lucian
相关产品推荐
相关产品推荐

