C++和Java在字符串循环方面的性能比较

3
我对使用Visual Studio Community Edition 2015实现的C ++和1.7版本的Java进行了一些循环性能测试。 以下是源代码: Java:
long startTime = 0;
long endTime = 0;
long totalTime = 0;

startTime = System.currentTimeMillis();
for (long counter = 0; counter < numberOfIterations; counter++)
{
    System.out.println("01234");
}
endTime = System.currentTimeMillis();
totalTime = endTime - startTime;

C++(基于Windows,发布版本x64,优化了速度):
ULONGLONG startTime = 0;
ULONGLONG endTime = 0;
ULONGLONG elapsedTime = 0;

startTime = GetTickCount64();
for (LONGLONG counter = 0; counter < numberOfIterations; counter++)
{
    cout << "01234" << endl;
}
endTime = GetTickCount64();
elapsedTime = endTime - startTime;

这是一段测试结果的文本,经过100,000次旋转/循环后,我真的感到惊讶。以下是结果:
Java: 1. 第一次尝试:31,361毫秒 2. 第二次尝试:6,316毫秒 3. 第三次尝试:6,865毫秒 C++: 1. 第一次尝试:40,000毫秒 2. 第二次尝试:37,703毫秒 3. 第三次尝试:20,734毫秒
然后我有另一组测试用例。
Java:
long startTime = 0;
long endTime = 0;
long totalTime = 0;
startTime = System.currentTimeMillis();
for(long counter = 0; counter < numberOfIterations; counter++) {
    String tempString = new String("test");
}
endTime = System.currentTimeMillis();

C++(基于Windows,发布版本x64,优化速度):
ULONGLONG startTime = 0;
ULONGLONG endTime = 0;
ULONGLONG elapsedTime = 0;

startTime = GetTickCount64();
for (LONGLONG counter = 0; counter < numberOfIterations; counter++)
{
    string tempString = "test";
}
endTime = GetTickCount64();
elapsedTime = endTime - startTime;

再次进行10,000,000次旋转/循环后,结果实际上更令人惊讶。以下是它们的结果: Java

  • 第一次尝试:7毫秒
  • 第二次尝试:7毫秒
  • 第三次尝试:7毫秒

C++:

  • 第一次尝试:125毫秒
  • 第二次尝试:125毫秒
  • 第三次尝试:125毫秒

但在空循环中,C++表现得更好。

在进行这个测试之前,我实际上认为C++在低级别或特定于操作系统/平台的实现方面总是优于Java。但是,在这种情况下,这是否意味着Java有更有效的处理字符串的方式,特别是如果它已经是大量的字符串?



谢谢


1
如何在Java中编写正确的微基准测试? - Andy Turner
5
这里的问题是:你的示例可能太过简单,无法得出有意义的数字。例如,请参阅https://dev59.com/hHRB5IYBdhLWcg3wz6UK。我的意思是:Java JIT进行了很多优化。它可能会迅速发现创建只会被丢弃的字符串对象没有意义。至于另一个测试用例:你明白当打印到控制台时(?),大部分时间都会花在系统调用上吗? - GhostCat
1
请在第一个C++示例中的循环之前添加两行代码: ios_base::sync_with_stdio(false);cin.tie(NULL);,然后再试一次? - DAle
2
endl 更改为 '\n' - Pete Becker
2
@PeteBecker:没有使用 endl 是正确的,因为 System.out.println 也会刷新缓冲区。公平起见,两种语言都应该刷新或不刷新。 - Andre Kampling
显示剩余11条评论
1个回答

1

最终,我抽出时间履行承诺,在此发表了答案。但是我很抱歉。无论如何,这是我收集到的统计数据,请耐心阅读,这是一个相当冗长的回答。顺便说一句,两者都在 Windows 10 Pro x64 机器上执行 =)!


第一段代码(包括C++和Java): 在Windows上使用Java:

public void testForLoopCreateInt(long numberOfIterations) {
    ArrayList<Integer> listOfIntegers = new ArrayList<Integer>();
    long startTime = 0;
    long endTime = 0;
    long totalTime = 0;
    System.out.println("\n===========================" + "\ntestForLoopCreateInt() Looping for: " + numberOfIterations);
    startTime = System.currentTimeMillis();
    for(long counter = 0; counter < numberOfIterations; counter++) {
        int i = 0;
        listOfIntegers.add(i);
    }
    endTime = System.currentTimeMillis();
    totalTime = endTime - startTime;
    System.out.println("Total time: " + totalTime + " milliseconds");

    System.out.println("===========================testForLoopCreateInt()");

    for (int indexer = 0; indexer < 10; indexer++) {
        int y = listOfIntegers.get(indexer);
    }
}

在C++中使用一些Win32 API:

void Loops::testForLoopCreateInt(LONGLONG numberOfIterations)
{
    cout << "\n===========================" << "\ntestForLoopCreateInt() Looping for: " << numberOfIterations << endl;
    vector<int> vectorOfInts;

    high_resolution_clock::time_point startTime = high_resolution_clock::now();
    for (LONGLONG counter = 0; counter < numberOfIterations; counter++)
    {
        int i = 0;
        vectorOfInts.push_back(i);
    }
    high_resolution_clock::time_point endTime = high_resolution_clock::now();

    duration<double, std::milli> totalTime = endTime - startTime;
    cout << "Total time: " << totalTime.count() << " milliseconds" << endl;
    cout << "===========================testForLoopCreateInt()" << endl;

    for (int indexer = 0; indexer < 10; indexer++) {
        int y = vectorOfInts.at(indexer);
    }
}

当每个迭代次数设置为某个值时,以下是结果:
Java:
- 10次迭代:0.00毫秒 - 100次迭代:0.00毫秒 - 1000次迭代:0.00毫秒 - 10000次迭代:1.00毫秒 - 100000次迭代:4.00毫秒 - 1000000次迭代:12.00毫秒 - 10000000次迭代:106.00毫秒 - 100000000次迭代:1,747.00毫秒
C++:
  • 10 次迭代:0.001803 毫秒
  • 100 次迭代:0.00601 毫秒
  • 1000 次迭代:0.013521 毫秒
  • 10000 次迭代:0.067005 毫秒
  • 100000 次迭代:0.506291 毫秒
  • 1000000 次迭代:4.4806 毫秒
  • 10000000 次迭代:61.1632 毫秒
  • 100000000 次迭代:679.341 毫秒

第二段代码(C++和Java): 在Windows上的Java:

public void testForLoopCreateUniformStringAndStoreToArrayList(long numberOfIterations) {
    ArrayList<String> listOfIntegers = new ArrayList<String>();
    long startTime = 0;
    long endTime = 0;
    long totalTime = 0;
    System.out.println("\n===========================" + "\ntestForLoopCreateUniformStringAndStoreToArrayList() Looping for: " + numberOfIterations);
    startTime = System.currentTimeMillis();
    for(long counter = 0; counter < numberOfIterations; counter++) {
        String string = new String("01234");
        listOfIntegers.add(string);
    }
    endTime = System.currentTimeMillis();
    totalTime = endTime - startTime;
    System.out.println("Total time: " + totalTime + " milliseconds");

    System.out.println("===========================testForLoopCreateUniformStringAndStoreToArrayList()");

    for (int indexer = 0; indexer < 10; indexer++) {
        String y = listOfIntegers.get(indexer);
    }
}

在使用一些Win32 API的C++中:

void Loops::testForLoopCreateUniformStringAndStoreToVector(LONGLONG numberOfIterations)
{
    cout << "\n===========================" << "\ntestForLoopCreateUniformStringAndStoreToVector() Looping for: " << numberOfIterations << endl;
    vector<string> vectorOfStrings;

    high_resolution_clock::time_point startTime = high_resolution_clock::now();
    for (LONGLONG counter = 0; counter < numberOfIterations; counter++)
    {
        string str000("01234");
        vectorOfStrings.push_back(str000);
    }
    high_resolution_clock::time_point endTime = high_resolution_clock::now();

    duration<double, std::milli> totalTime = endTime - startTime;
    cout << "Total time: " << totalTime.count() << " milliseconds" << endl;
    cout << "===========================testForLoopCreateUniformStringAndStoreToVector()" << endl;

    for (int indexer = 0; indexer < 10; indexer++) {
        string y = vectorOfStrings.at(indexer);
    }
}

当每个迭代次数设置为某个值时,以下是结果:

Java:

  • 10次迭代:0.00毫秒
  • 100次迭代:0.00毫秒
  • 1000次迭代:1.00毫秒
  • 10000次迭代:1.00毫秒
  • 100000次迭代:6.00毫秒
  • 1000000次迭代:24.00毫秒
  • 10000000次迭代:2,742.00毫秒
  • 100000000次迭代:33,371.00毫秒

C++:

  • 10次迭代:0.003605毫秒
  • 100次迭代:0.018329毫秒
  • 1000次迭代:0.064301毫秒
  • 10000次迭代:0.71722毫秒
  • 100000次迭代:13.9406毫秒
  • 1000000次迭代:88.5781毫秒
  • 10000000次迭代:931.526毫秒
  • 100000000次迭代:10,768.9毫秒

这些是结果,我不确定这是否有偏见,但我会尽可能公平地让C++(在Windows上)与Java(在Windows上)进行比较。所以你可以自行判断。

谢谢。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接