为什么 std::string 操作表现不佳?

新手上路,请多包涵

我做了一个测试来比较几种语言的字符串操作,以便为服务器端应用程序选择一种语言。结果似乎很正常,直到我终于尝试了 C++,这让我很惊讶。所以我想知道我是否错过了任何优化并来这里寻求帮助。

测试主要是密集的字符串操作,包括连接和搜索。测试在 Ubuntu 11.10 amd64 上执行,GCC 版本为 4.6.1。该机器是戴尔 Optiplex 960,具有 4G RAM 和四核 CPU。

在 Python (2.7.2) 中:

 def test():
    x = ""
    limit = 102 * 1024
    while len(x) < limit:
        x += "X"
        if x.find("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0) > 0:
            print("Oh my god, this is impossible!")
    print("x's length is : %d" % len(x))

test()

这给出了结果:

 x's length is : 104448

real    0m8.799s
user    0m8.769s
sys     0m0.008s

在 Java (OpenJDK-7) 中:

 public class test {
    public static void main(String[] args) {
        int x = 0;
        int limit = 102 * 1024;
        String s="";
        for (; s.length() < limit;) {
            s += "X";
            if (s.indexOf("ABCDEFGHIJKLMNOPQRSTUVWXYZ") > 0)
            System.out.printf("Find!\n");
        }
        System.out.printf("x's length = %d\n", s.length());
    }
}

这给出了结果:

 x's length = 104448

real    0m50.436s
user    0m50.431s
sys     0m0.488s

在 Javascript (Nodejs 0.6.3)

 function test()
{
    var x = "";
    var limit = 102 * 1024;
    while (x.length < limit) {
        x += "X";
        if (x.indexOf("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0) > 0)
            console.log("OK");
    }
    console.log("x's length = " + x.length);
}();

这给出了结果:

 x's length = 104448

real    0m3.115s
user    0m3.084s
sys     0m0.048s

在 C++ 中 (g++ -Ofast)

Nodejs 的性能优于 Python 或 Java 也就不足为奇了。但我预计 libstdc++ 会比 Nodejs 提供更好的性能,它的结果真的让我吃惊。

 #include <iostream>
#include <string>
using namespace std;
void test()
{
    int x = 0;
    int limit = 102 * 1024;
    string s("");
    for (; s.size() < limit;) {
        s += "X";
        if (s.find("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 0) != string::npos)
            cout << "Find!" << endl;
    }
    cout << "x's length = " << s.size() << endl;
}

int main()
{
    test();
}

这给出了结果:

 x length = 104448

real    0m5.905s
user    0m5.900s
sys     0m0.000s

简要总结

好的,现在让我们看看摘要:

  • Nodejs(V8)上的javascript:3.1s
  • CPython 2.7.2 上的 Python:8.8 秒
  • 带有 libstdc++ 的 C++:5.9 秒
  • OpenJDK 7 上的 Java:50.4 秒

出奇!我在 C++ 中尝试了“-O2,-O3”,但注意到有帮助。在 V8 中,C++ 的性能似乎只有 javascript 的 50%,甚至比 CPython 还要差。如果我错过了 GCC 中的一些优化,谁能向我解释一下,或者只是这种情况?十分感谢。

原文由 Wu Shu 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 386
1 个回答

不是 std::string 表现不佳(尽管我不喜欢 C++),而是字符串处理针对其他语言进行了如此严格的优化。

您对字符串性能的比较具有误导性,并且如果它们旨在代表更多内容,则它们是冒昧的。

我知道 Python 字符串对象完全在 C 中实现,实际上在 Python 2.7 上,由于 unicode 字符串和字节之间缺乏分离,存在 许多 优化。如果您在 Python 3.x 上运行此测试,您会发现它的速度要慢得多。

Javascript 有许多高度优化的实现。可以预料,这里的字符串处理非常好。

您的 Java 结果可能是由于不正确的字符串处理或其他一些糟糕的情况。我希望 Java 专家可以介入并通过一些更改来修复此测试。

至于您的 C++ 示例,我预计性能会略微超过 Python 版本。它执行相同的操作,但解释器开销更少。这反映在您的结果中。在测试之前使用 s.reserve(limit); 将消除重新分配开销。

我再重复一遍,您只是在测试语言 实现 的一个方面。此测试的结果不反映整体语言速度。

我提供了一个 C 版本来展示这种小便比赛是多么愚蠢:

 #define _GNU_SOURCE
#include <string.h>
#include <stdio.h>

void test()
{
    int limit = 102 * 1024;
    char s[limit];
    size_t size = 0;
    while (size < limit) {
        s[size++] = 'X';
        if (memmem(s, size, "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26)) {
            fprintf(stderr, "zomg\n");
            return;
        }
    }
    printf("x's length = %zu\n", size);
}

int main()
{
    test();
    return 0;
}

定时:

 matt@stanley:~/Desktop$ time ./smash
x's length = 104448

real    0m0.681s
user    0m0.680s
sys     0m0.000s

原文由 Matt Joiner 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题