我的PC运行的是Windows 10,CPU为I5-4670K(4 Ghz),而Plextor 512G SSD为C驱动器,其中Pharo 5.0已加载并运行.
下面是我用来理解Pharo在性能和计算精度方面的行为的一组代码.
| x y | x := 0. y := 400000000. [1 to: 2000000000 do: [ :i | x := x + 0.2]] timeToRun
执行需要2分钟8.281秒.如果我从迭代次数中剔除一个零,那么完成只需1.762秒.迭代次数超过执行时间的70倍以上.似乎我遇到了一个系统边界,这样两个案例之间的执行时间增长远远超过10倍.
欣赏任何提示,并帮助微调Pharo 5.0 VM,以便我可以减少这种意外和不良的系统行为?
附:在执行期间,Windows任务管理器未报告磁盘活动的任何更改.几乎所有执行都是RAM和CPU操作.顺便说一句,除非你有一个更快的PC,请不要尝试在迭代次数上添加另一个零,花了这么长时间我不得不打破执行.
欢迎来到SO(以及smalltalk标签!)首先请注意临时y在这里没有扮演任何角色,所以我们可以简化一些片段
| x | x := 0. [1 to: 200000000 * 10 do: [ :i | x := x + 0.2]] timeToRun
你比较的
| x | x := 0. [1 to: 200000000 * 1 do: [ :i | x := x + 0.2]] timeToRun
第一个版本的原因不仅仅是第二个版本慢了10倍,而前者是块变量i从SmallInteger域移动到LargeInteger域.因此,每当块增加i时,当我超过SmallInteger边界时,此处发生的加法i:= i 1涉及LargeInteger算法,它比SmallInteger算法慢.
那么LargeInteger算术会发生多少次?好吧,要计算我们只需要从200000000 * 10中减去SmallInteger maxVal:
(200000000 * 10) - SmallInteger maxVal = 926,258,177
意思是Pharo在大整数i上执行那么多次操作.
请注意,如果我们有的话
| x | x := 0. [ 10 timesRepeat: [1 to: 200000000 * 1 do: [ :i | x := x + 0.2]] ] timeToRun
我们花费的时间大约是一次迭代的10倍.
附录
请不要将上面的解释视为表明LargeInteger算术在Pharo中表现不佳.相反,Pharo在使这样的计算有效方面做得很好.
幕后花絮Pharo使用基元进行这些操作,同时为程序员提供了一个独特且一致的视图和Integer算术API.事实上,如果你试图在另一个没有VM支持LargeInteger的方言中做同样的事情,你将不得不等待很长时间才能得到计算结果.