C ++(Intel)vs Java(Hotspot)与C#基准测试问题(包括代码和结果)

时间:2012-04-21 14:52:59

标签: c# java c++ performance caching

我一直在比较三种主要语言之间的原始CPU性能速度(代码和结果如下)。我很好奇主要语言如何比较原始计算能力。我有一个理论认为,当没有涉及内存开销时,Java和C#可能与C ++相媲美。

我的问题:

1)编辑(C ++时序现在更加真实)

2)我是否正确地认为JVM在第一次迭代中花费了很长时间,但是对于第二次迭代它已经完成分析并因此进行了优化? Hotspot如何知道在我的外部循环的第一次迭代之后完成优化而不是中途?

3)为什么C#不像Java那样执行并且在开始时进行了大量优化?有关Java的C#有何不同?为什么C#较慢 - 仅仅是因为优化程度较低?

4)对于C#测试时序,2246和2262毫秒之间的振荡是否有任何具体原因,这可能是两个不同的时间,因为CPU有两个内核?

编辑:更新代码以在C#代码中显示秒表使用情况。

编辑:纠正C ++时序代码和结果

设置:

  • C ++:VS2010和英特尔编译器(内置发布模式,优化: O2,启用内在功能:是的,有利于大小和速度:不, 省略帧指针:否,启用光纤安全优化:不,整体 程序优化:是)

  • Java:Eclipse,Hotspot 64位编译器版本17,Java 1.6

  • C#:VS2010和.net 4.0(内置于发布模式)

  • CPU:Intel E6600(2.4GHz)运行速度为2.7GHz,总线速度为300MHz,内存为8GB,DRAM频率为:375MHz

  • 赢7(64位)

C ++代码:

#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <windows.h>
#include <mmsystem.h>
#include <stdio.h>
#include <fstream> 

using namespace std;


double PCFreq = 0.0;
__int64 CounterStart = 0;

void StartCounter()
{
    LARGE_INTEGER li;
    if(!QueryPerformanceFrequency(&li))
        cout << "QueryPerformanceFrequency failed!\n";

    PCFreq = li.QuadPart;

    QueryPerformanceCounter(&li);
    CounterStart = li.QuadPart;
}
double GetCounter()
{
    LARGE_INTEGER li;
    QueryPerformanceCounter(&li);
    return double(li.QuadPart-CounterStart)/PCFreq;
}

static long counter = 0;

int _tmain(int argc, _TCHAR* argv[])
{

    for (int m = 0; m < 10; m++)
    {
        StartCounter();
        counter = 0;

        for (int j = 0; j < 3; j++)
        {
            //Just to test timing is working correctly
            //int* p = new int;

            for (long i = 0; i < 200000000; i++)
            {
                counter++;
            }
        }

        cout << GetCounter()*1000000 << " microseconds" << endl;
    }


    int p = 0;
    cin >> p;
    return 0;
}

C ++结果:

  

7.19微秒

     

1.89

     

2.27

     

1.51

     

4.92

     

10.22

     

10.22

     

9.84

     

9.84

     

10.6

Java代码:

public class main {

    static long counter = 0;

    public static void main(String[] args) {

        for(int m=0; m<10; m++){
            long start = System.nanoTime();
            counter = 0;

            for(int j=0;j<3; j++){
                for(long i=0; i<200000000; i++){
                    counter++;
                }
            }

            System.out.println(((System.nanoTime()-start)/1000000) + " ms");
        }
    }
}

Java结果:

5703 milliseconds
471 ms
468 ms
467 ms
469 ms
467 ms
467 ms
467 ms
469 ms
464 ms

C#代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics

namespace t1
{
    class Program
    {
        static long counter = 0;

        static void Main(string[] args)
        {
            for (int m = 0; m < 10; m++)
            {
                Stopwatch s = new Stopwatch();
                s.Start();
                counter = 0;

                for (int j = 0; j < 3; j++)
                {

                    for (long i = 0; i < 200000000; i++)
                    {
                        counter++;
                    }

                }
                s.Stop();
                Console.WriteLine(s.Elapsed.TotalMilliseconds + " ms");
            }

            Console.ReadLine();
        }
    }
}

C#结果:

  

2277毫秒

     

2246 ms

     

2262 ms

     

2246 ms

     

2262 ms

     

2246 ms

     

2262 ms

     

2246 ms

     

2262 ms

     

2262 ms

4 个答案:

答案 0 :(得分:2)

您的C ++代码中存在使用QueryPerformanceFrequency

的逻辑问题
PCFreq = double(li.QuadPart)/1000000000.0; // <- this is not correct
PCFreq = li.QuadPart;                      // <- this is correct

您应该将li.QuadPart分配给PCFreq并在打印代码中转换为毫秒或纳秒:

// convert from seconds to milliseconds
cout << GetCounter() * 1000.0 << endl;

通过此更改,我获得了C ++代码的实际时间。无论这些时间是否“有效”或有用于比较,我都不会发表评论。

答案 1 :(得分:2)

1 - Sixlettervararia似乎已经指出了你的错误

2 - 热点将优化代码。这是一个类似的问题,它也看到循环上10倍的加速。所以你看到的是预期产量。 First time a Java loop is run SLOW, why? [Sun HotSpot 1.5, sparc]

3 - 我对C#的了解不够充分。它可能不会优化内部循环(您有3个不同的循环)。也许尝试将您正在测试的2个循环提取到一个完全独立的方法中,看看是否有帮助。

4 - DateTime表示日期和时间,而不是高精度计时。因此,它并不准确。据我所知,DateTime.Now的分辨率为10ms

(仅供参考,这篇文章对JIT,C#和C ++优化提供了一些很好的解释,可以帮助你:C++ performance vs. Java/C#

答案 2 :(得分:1)

我认为编译器可能会在编译时计算计数器的值而不会遍历循环。

我认为一个简单的计数器是一个非常糟糕的基准。

顺便说一句,尝试在方法中运行java代码。由于JIT优化,它可能更快。 (但我不确定)

答案 3 :(得分:1)

各种编译器的基准已经完成并且非常好地组合在一起。

The Computer Language Benchmark Games

Java 7 Server vs. GNU C++

C# Mono vs. GNU C++

C# Mono vs Java 7 Server

虽然Java 7 Server比C#Mono 2.10.8更快,但请查看Java 7使用的内存量。