有谁知道Pharo和Squeak的Cog VM是否能够使用这样的访问器优化简单的间接变量访问:
SomeClass>>someProperty
^ someProperty
SomeClass>>someSecondProperty
^ someSecondProperty
只返回一个实例变量,所以像这样的方法:
SomeClass>>someMethod
^ self someProperty doWith: self someSecondProperty
将不会比这样的方法慢:
SomeClass>>someMethod
^ someProperty doWith: someSecondProperty
我做了一些基准测试,看起来它们的速度大致相当,但我很好奇是否有人熟悉Cog确实知道,因为如果存在差异(无论多么微小),那么可能会有但是在一个人不合适的情况下很少见。
答案 0 :(得分:2)
这是一个棘手的问题......而且我不知道确切的答案。但我可以帮助你学习如何自己检查一些线索。
您需要在图片中加载VMMaker包。在Pharo中,有一个程序可以通过从net和github下载所有内容来构建这样的图像。见https://github.com/pharo-project/pharo-vm
然后主要提示是,只返回实例变量的方法被编译为执行原语264 + inst var offset ...(例如,您通过检查Interval>>#first
或任何其他方式看到这一点其他简单的inst var getter)
在经典解释器VM中,这是在Interpreter>>internalExecuteNewMethod
中处理的
看起来您支付方法查找的成本(一些缓存使这更便宜),但不是真正的方法激活。
我想它解释了调试器无法进入这种简单的方法......但这并不是真正的内联。
在COG中,如果使用解释器,StackInterpreter>>internalQuickPrimitiveResponse
也会发生同样的情况。
对于JIT,这由Cogit>>compilePrimitive
处理,另见genQuickReturnInstVar
的实现者。这也不是正确的内联,但您可以看到生成的指令非常少。再说一次,我敢打赌你一般不会为了所谓的多态内联缓存(PIC)而付出代价。
对于真正的内联,在快速浏览源代码后我没有找到线索...
我的理解是,它将通过Sista VM的回调在图像方面发生,但这是正在进行的工作,只有我模糊的回忆。克莱门特贝拉正在写一篇关于这个的博客(在http://clementbera.wordpress.com)
如果您害怕挖掘VMMaker源代码,我邀请您在vm-dev.lists.squeakfoundation.org上询问我很确定Eliot Miranda或Clement很乐意为您提供帮助更准确的答案。
修改强>
我忘了告诉你关于上述影响的结论:如果你直接使用inst,我认为会有很小的差异。变种。而不是一个吸气剂,但这不应该是真正引人注目的,并且在所有情况下,你的编程风格不应该被这种可忽略的优化引导。
答案 1 :(得分:2)
现在有点费用,但它太少了,你不应该打扰。如果您想要性能,您愿意更改代码的其他部分,而不是实例变量访问。
快速的替补席: 长凳 ^ {[iv你自己]替补。 [自我自己]替补席} => #('每秒52,400,000。''每秒49,800,000。') 差异看起来不那么大。
一旦jitted并执行一次,不同之处在于" self iv"除了获取实例变量值之外,还执行内联高速缓存检查,cpu调用和cpu返回。调用和返回指令很可能是由cpu预期而不是真正执行的。所以关于内联缓存检查这是一个非常便宜的操作。
开发中的内联编译器将添加的是cpu调用和返回实际上将通过内联删除,这将涵盖cpu没有预料到它们的情况。此外,根据具体情况,可能会也可能不会删除内联缓存检查。
有一些细节,例如需要将getter方法编译为本机代码,这在机器代码区占用空间,这可能会增加机器代码区垃圾收集的数量,但这比内联更加轶事缓存检查开销。
简而言之,目前开销非常小,但未来开销会减少。
克莱门特