Cup*_*tor 5 python java string performance concatenation
更新:非常感谢Gabe和Glenn的详细解释.该测试不是用于语言比较基准,而是为了研究VM优化技术.
我做了一个简单的测试来理解Java和Python之间字符串连接的性能.
该测试是两种语言中默认不可变String对象/类型的目标.所以我不在Java测试中使用StringBuilder/StringBuffer.
测试只需添加100k次的字符串.Java消耗约32秒完成,而Python仅使用约13秒的Unicode字符串和0.042秒的非Unicode字符串.
我对结果有点惊讶.我认为Java应该比Python更快.Python利用什么优化技术来实现更好的性能?或者String对象在Java中设计得太重了?
操作系统:Ubuntu 10.04 x64 JDK:Sun 1.6.0_21 Python:2.6.5
Java测试确实使用-Xms1024m来最小化GC活动.
Java代码:
public class StringConcateTest {
public static void test(int n) {
long start = System.currentTimeMillis();
String a = "";
for (int i = 0; i < n; i++) {
a = a.concat(String.valueOf(i));
}
long end = System.currentTimeMillis();
System.out.println(a.length() + ", time:" + (end - start));
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
test(1000 * 100);
}
}
Run Code Online (Sandbox Code Playgroud)
}
Python代码:
import time
def f(n):
start = time.time()
a = u'' #remove u to use non Unicode string
for i in xrange(n):
a = a + str(i)
print len(a), 'time', (time.time() - start)*1000.0
for j in xrange(10):
f(1000 * 100)
Run Code Online (Sandbox Code Playgroud)
@ Gabe的答案是正确的,但需要清楚地展示而不是假设.
CPython(可能只有CPython)会在可能的情况下附加就地字符串.它何时可以做到这一点有局限性.
首先,它不能用于实习字符串.这就是为什么你在测试时永远不会看到这个a = "testing"; a = a + "testing",因为分配一个字符串文字导致一个实习字符串.您必须动态创建字符串,就像此代码一样str(12345).(这不是一个限制;一旦你以这种方式附加一次,结果是一个未处理的字符串,所以如果你在循环中追加字符串文字,这只会在第一次发生.)
其次,Python 2.x只能这样做str,而不是unicode.Python 3.x确实为Unicode字符串执行此操作.这很奇怪:这是一个主要的性能差异 - 复杂性的差异.这不鼓励在2.x中使用Unicode字符串,因为它们应该鼓励它来帮助过渡到3.x.
最后,没有其他对字符串的引用.
>>> a = str(12345)
>>> id(a)
3082418720
>>> a += str(67890)
>>> id(a)
3082418720
Run Code Online (Sandbox Code Playgroud)
这解释了为什么非Unicode版本在测试中比Unicode版本快得多.
这样做的实际代码是string_concatenate在Python/ceval.c和同时适用于s1 = s1 + s2和s1 += s2.该功能_PyString_Resize在Objects/stringobject.c还明确地说:下面的函数打破的概念,字符串是不可变的.另见http://bugs.python.org/issue980695.
| 归档时间: |
|
| 查看次数: |
1951 次 |
| 最近记录: |