Java 为什么Jython在使用PyStone进行测试时表现不一致?

Java 为什么Jython在使用PyStone进行测试时表现不一致?,java,python,performance,jython,benchmarking,Java,Python,Performance,Jython,Benchmarking,我最近和Jython一起玩,决定用pystone做一些快速而肮脏的基准测试。为了获得参考,我首先测试了cPython 2.6,循环的数量不断增加(我认为这可能是相关的,因为Jython应该在一段时间后才开始从JIT中获益) 正如您所看到的,cPython的行为是一致的:完成测试所需的时间随着循环数的增加而线性增加。知道了这一点,我开始测试Jython (richard garibaldi):/usr/local/src/pybench% jython ~/tmp/pystone.py Pyst

我最近和Jython一起玩,决定用pystone做一些快速而肮脏的基准测试。为了获得参考,我首先测试了cPython 2.6,循环的数量不断增加(我认为这可能是相关的,因为Jython应该在一段时间后才开始从JIT中获益)

正如您所看到的,cPython的行为是一致的:完成测试所需的时间随着循环数的增加而线性增加。知道了这一点,我开始测试Jython

(richard garibaldi):/usr/local/src/pybench% jython ~/tmp/pystone.py 
Pystone(1.1) time for 50000 passes = 2.29807
This machine benchmarks at 21757.4 pystones/second

(richard garibaldi):/usr/local/src/pybench% jython ~/tmp/pystone.py 500000 
Pystone(1.1) time for 500000 passes = 10.931
This machine benchmarks at 45741.4 pystones/second


(richard garibaldi):/usr/local/src/pybench% jython ~/tmp/pystone.py 1000000
Pystone(1.1) time for 1000000 passes = 107.183
This machine benchmarks at 9329.86 pystones/second
在第一次跑步中,Jython与它的C兄弟相比跑得相当糟糕。当增加循环数时,它开始感觉更好,接近cPython,就像我最初的假设预测的那样。请注意,循环的数量增加了10倍,但Jython只花了大约5倍的时间来完成它们。所以,正如你想象的那样,我原以为Jython会在最后的测试中表现出色。然而,令我非常失望的是,它确实很糟糕:比最初运行时慢了两倍多

你的假设是什么:为什么Jython的行为如此不一致?可能是GC在某个时刻开始工作,并且花费了很多时间吗?我看过PyStone的代码,垃圾收集似乎没有关闭,但我希望Java的GC至少和Python的一样好。。。您认为这种减速是永久性的,还是在增加循环数后会在某个时候消失?Jython在一个长时间运行的进程中应该如何表现

编辑:不幸的是,如果我将循环数增加到200万,我会得到
java.lang.OutOfMemoryError

(当然,Jython仍然是测试版,所以在最终版本中应该会更好。)

我正在MacOS X 10.5上使用Jython 2.5b1(主干:5903:59052009年1月9日,16:01:29)、Java(TM)SE运行时环境(构建1.6.0_07-b06-153)和Java HotSpot(TM)64位服务器虚拟机(构建1.6.0_07-b06-57,混合模式)


感谢您的回答。

我非常肯定,通过调整JVM配置可以改善结果(JRuby使用了很多有趣的标志来实现这一点),而且我也非常肯定垃圾收集可以进行调优。 如果您对这个基准非常感兴趣,这里有一个很好的资源来配置您的VM:。我还要看一下JRuby配置


/alex

这可能是jython 2.5b1中的一个bug。你应该考虑把它报告给Jython团队。我刚刚用jython(2.2.1)的最新稳定版本在我的MacBook上运行了pystone基准测试,我得到了缓慢但一致的结果:

mo$ ~/Coding/Jython/jython2.2.1/jython pystone.py 50000
Pystone(1.1) time for 50000 passes = 2.365
This machine benchmarks at 21141.6 pystones/second

mo$ ~/Coding/Jython/jython2.2.1/jython pystone.py 500000
Pystone(1.1) time for 500000 passes = 22.246
This machine benchmarks at 22476 pystones/second

mo$ ~/Coding/Jython/jython2.2.1/jython pystone.py 1000000
Pystone(1.1) time for 1000000 passes = 43.94
This machine benchmarks at 22758.3 pystones/second

mo$ java -version
java version "1.5.0_16"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_16-b06-275)
Java HotSpot(TM) Client VM (build 1.5.0_16-132, mixed mode, sharing)
对我来说,cPython的结果或多或少是一样的。我重新进行了三次测试,每次都得到了非常相似的结果

我还尝试给java一个更大的初始堆和最大堆(-Xms256m-Xmx512m),但没有得到值得注意的结果

但是,将JVM设置为服务器(启动速度较慢,长时间运行性能更好,不太适合“交互式”工作)稍微改变了局面:

mo$ ~/Coding/Jython/jython2.2.1/jython pystone.py 50000
Pystone(1.1) time for 50000 passes = 1.848
This machine benchmarks at 27056.3 pystones/second

mo$ ~/Coding/Jython/jython2.2.1/jython pystone.py 500000
Pystone(1.1) time for 500000 passes = 9.998
This machine benchmarks at 50010 pystones/second

mo$ ~/Coding/Jython/jython2.2.1/jython pystone.py 1000000
Pystone(1.1) time for 1000000 passes = 19.9
This machine benchmarks at 50251.3 pystones/second
我使用(-server-Xms256m-Xmx512m)进行了最后一次运行:

我的猜测是,第一次运行缓慢是因为VM启动/JIT尚未真正启动。长时间运行的结果或多或少是一致的,并且显示了hotspot/JIT的效果


也许你可以用更大的堆重新运行上一次测试?要更改JVM开关,只需在jython安装中编辑jython文件。

XP\u Win32\u PC上的我的工作台:

C:\jython\jython2.5b1>bench "50000"

C:\jython\jython2.5b1>jython Lib\test\pystone.py "50000"
Pystone(1.1) time for 50000 passes = 1.73489
This machine benchmarks at 28820.2 pystones/second

C:\jython\jython2.5b1>bench "100000"

C:\jython\jython2.5b1>jython Lib\test\pystone.py "100000"
Pystone(1.1) time for 100000 passes = 3.36223
This machine benchmarks at 29742.2 pystones/second

C:\jython\jython2.5b1>bench "500000"

C:\jython\jython2.5b1>jython Lib\test\pystone.py "500000"
Pystone(1.1) time for 500000 passes = 15.8116
This machine benchmarks at 31622.3 pystones/second

C:\jython\jython2.5b1>bench "1000000"

C:\jython\jython2.5b1>jython Lib\test\pystone.py "1000000"
Pystone(1.1) time for 1000000 passes = 30.9763
This machine benchmarks at 32282.8 pystones/second

C:\jython\jython2.5b1>jython
Jython 2.5b1 (trunk:5903:5905, Jan 9 2009, 16:01:29)
[Java HotSpot(TM) Client VM (Sun Microsystems Inc.)] on java1.5.0_17
它不是那么快,但是

没有“特效”

这是java虚拟机的“问题”吗


如果您想进一步了解我在这台旧的Win32 PC上的基准测试,请添加一条评论。我的笔记本电脑运行的是UbuntuJaunty,JRE 1.6.0_12-b04,测试结果与此相同:

nathell@breeze:/usr/lib/python2.5/test$ python pystone.py 500000 Pystone(1.1) time for 500000 passes = 12.98 This machine benchmarks at 38520.8 pystones/second nathell@breeze:/usr/lib/python2.5/test$ python pystone.py 1000000 Pystone(1.1) time for 1000000 passes = 26.05 This machine benchmarks at 38387.7 pystones/second nathell@breeze:/usr/lib/python2.5/test$ ~/jython/jython pystone.py Pystone(1.1) time for 50000 passes = 2.47788 This machine benchmarks at 20178.6 pystones/second nathell@breeze:/usr/lib/python2.5/test$ ~/jython/jython pystone.py 500000 Pystone(1.1) time for 500000 passes = 19.7294 This machine benchmarks at 25342.9 pystones/second nathell@breeze:/usr/lib/python2.5/test$ ~/jython/jython pystone.py 1000000 Pystone(1.1) time for 1000000 passes = 38.9272 This machine benchmarks at 25689 pystones/second nathell@breeze:/usr/lib/python2.5/test$python pystone.py 500000 派斯通(1.1)500000次通过的时间=12.98 这台机器的基准速度为38520.8皮斯通/秒 nathell@breeze:/usr/lib/python2.5/test$python pystone.py 1000000 Pystone(1.1)1000000次通过的时间=26.05 这台机器的基准速度为38387.7皮斯通/秒 nathell@breeze:/usr/lib/python2.5/test$~/jython/jython pystone.py Pystone(1.1)50000次通过的时间=2.47788 这台机器的基准速度为20178.6皮斯通/秒 nathell@breeze:/usr/lib/python2.5/test$~/jython/jython pystone.py 500000 派斯通(1.1)500000次通过的时间=19.7294 这台机器的基准速度为25342.9皮斯通/秒 nathell@breeze:/usr/lib/python2.5/test$~/jython/jython-pystone.py 1000000 Pystone(1.1)1000000次通过的时间=38.9272 这台机器的基准速度是25689皮斯通/秒
因此,说到底,这可能与JRE有关,而不是与Jython版本有关。Armed Bear Common Lisp项目在早期版本的JRE 1.6中遇到的问题也可能暗示了这一点。

在JVM如此复杂的运行时环境中进行基准测试非常困难。即使不包括JIT和GC,在运行之间也有很大的堆、内存布局和缓存变化

Jython的一个帮助是在单个VM会话中多次运行基准测试:一次预热JIT,一次或多次单独测量。我已经做了很多Jython基准测试,不幸的是,通常需要10-50次尝试才能达到合理的时间

您可以使用一些JVM标志来观察GC和JIT行为,以了解预热期应该有多长,尽管显然不应该在调试标志打开时进行基准测试。例如:

% ./jython -J-XX:+PrintCompilation -J-verbose:gc
  1       java.lang.String::hashCode (60 bytes)
  2       java.lang.String::charAt (33 bytes)
  3       java.lang.String::lastIndexOf (156 bytes)
  4       java.lang.String::indexOf (151 bytes)
[GC 1984K->286K(7616K), 0.0031513 secs]
如果您做了所有这些,并使用HotSpot服务器VM,您会发现Jython比Python上的CPython稍微快一点,但这绝不能代表Jython的总体性能。Jython开发人员对2.5版本的正确性比性能更为关注;在未来一年左右的时间里,2.6/2.7/3.0版本的性能将更加突出。通过查看我运行的一些(最初源自PyPy)代码,您可以看到一些痛点

nathell@breeze:/usr/lib/python2.5/test$ python pystone.py 500000 Pystone(1.1) time for 500000 passes = 12.98 This machine benchmarks at 38520.8 pystones/second nathell@breeze:/usr/lib/python2.5/test$ python pystone.py 1000000 Pystone(1.1) time for 1000000 passes = 26.05 This machine benchmarks at 38387.7 pystones/second nathell@breeze:/usr/lib/python2.5/test$ ~/jython/jython pystone.py Pystone(1.1) time for 50000 passes = 2.47788 This machine benchmarks at 20178.6 pystones/second nathell@breeze:/usr/lib/python2.5/test$ ~/jython/jython pystone.py 500000 Pystone(1.1) time for 500000 passes = 19.7294 This machine benchmarks at 25342.9 pystones/second nathell@breeze:/usr/lib/python2.5/test$ ~/jython/jython pystone.py 1000000 Pystone(1.1) time for 1000000 passes = 38.9272 This machine benchmarks at 25689 pystones/second
% ./jython -J-XX:+PrintCompilation -J-verbose:gc
  1       java.lang.String::hashCode (60 bytes)
  2       java.lang.String::charAt (33 bytes)
  3       java.lang.String::lastIndexOf (156 bytes)
  4       java.lang.String::indexOf (151 bytes)
[GC 1984K->286K(7616K), 0.0031513 secs]