java - Java 和 Python 之间不可变字符串连接的性能比较

标签 java python performance string concatenation

更新:非常感谢 Gabe 和 Glenn 的详细解释。该测试不是为了语言比较基准而编写的,只是为了我对VM优化技术的研究。

我做了一个简单的测试来了解 Java 和 Python 之间字符串连接的性能。

测试的目标是两种语言中默认的不可变字符串对象/类型。所以我在 Java 测试中不使用 StringBuilder/StringBuffer。

该测试只是将字符串相加 10 万次。 Java 耗时约 32 秒完成,而 Python 仅使用 ~13 秒处理 Unicode 字符串,0.042 秒处理非 Unicode 字符串。

我对结果有点意外。我认为 Java 应该比 Python 快。 Python 利用什么优化技术来获得更好的性能?还是 String 对象在 Java 中设计得太重了?

操作系统:Ubuntu 10.04 x64 JDK:太阳 1.6.0_21 python :2.6.5

Java 测试确实使用了 -Xms1024m 来最小化 GC Activity 。

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);           
    }
}

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)

最佳答案

@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

这解释了为什么非 Unicode 版本在测试中比 Unicode 版本快得多。

实际代码是 Python/ceval.c 中的 string_concatenate,适用于 s1 = s1 + s2s1 += s2Objects/stringobject.c 中的函数 _PyString_Resize 也明确指出:以下函数打破了字符串不可变的概念。另见 http://bugs.python.org/issue980695 .

关于java - Java 和 Python 之间不可变字符串连接的性能比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3901124/

相关文章:

java - 带有对象的ArrayList

java - 我的电脑缺少 R.java

具有 CompletableFuture 的 Java 8 线程 : Shutdown after supplyAsync()?

python - 使用 pandas 在列表列表中查找所有匹配组

python - Seaborn 和 Matplotlib 添加相对于轴的文本

c# - 搜索字符串中每个出现的子字符串 C#

java - Camel CXF : IllegalArgumentException parameters should be of type X

python - 将此数据读入 pandas 数据框的优雅方法?

javascript - Sencha Touch 2 - Android 性能

java - AbstractStringBuilder 可能的性能增强