我一直在比较三种主要语言之间的原始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
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
答案 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比C#Mono 2.10.8更快,但请查看Java 7使用的内存量。