今天闲得无聊,突发奇想,做了一个Java和C++的性能对比测试。
1 测试方法
很简单的,就是分别让Java程序和C++程序做很多次的整数和浮点数运算,然后测量测试代码段的运行时间。C++代码中使用Windows函数QueryPerformanceCounter() 获取CPU的高精度计数值,测试开始前后分别获取一次计数值,使用Windows函数QueryPerformanceFrequency()获取运行频率,前后的计数差值除以频率就得到了运行时间。为了使时间测量基准一致,在Java程序中通过JNI去调用这两个Windows函数,测量Java程序的运行时间。
下面分别给出代码。
2 C++测试代码
#include "stdafx.h"
#include "windows.h"
#include <iostream>
#include <cmath>
using namespace std;
const int INT_C = 200000;
const int DOU_C = 50000;
const int MAIN_C = 10000;
class Test {
public:
Test();
void testInt();
void testDouble();
void doTest();
private:
int m_i;
double m_d;
};
Test::Test()
{
m_i = 0;
m_d = 0.0;
}
void Test::testInt()
{
for (int i=1;i<= INT_C;i++) {
m_i = (~(i*7) + 0x963 - i) & (i / 3);
}
}
void Test::testDouble()
{
for (int i=1;i<= DOU_C;i++) {
m_d = ((i<<2) + 0.36954) * sin((double)i);
}
}
void Test::doTest()
{
testInt();
testDouble();
}
int _tmain(int argc, _TCHAR* argv[])
{
LARGE_INTEGER freq;
LARGE_INTEGER start;
LARGE_INTEGER end;
QueryPerformanceFrequency(&freq);
Test* test = NULL;
int j;
cout<<"start test..."<<endl;
QueryPerformanceCounter(&start);
for (j = 0;j < MAIN_C; j++) {
test = new Test();
test->doTest();
delete test;
}
QueryPerformanceCounter(&end);
double druation = ((double)(end.QuadPart - start.QuadPart)) / ((double)freq.QuadPart);
cout<<"Program run druation: "<<druation*1000<<" ms."<<endl;
return 0;
}
3 Java测试代码
3.1 测试代码
public class PerformTest {
public static final int INT_C = 200000;
public static final int DOU_C = 50000;
public static final int MAIN_C = 10000;
private int m_i;
private double m_d;
public void testInt() {
for (int i=1;i<= INT_C;i++) {
m_i = (~(i*7) + 0x963 - i) & (i / 3);
}
}
public void testDouble() {
for (int i=1;i<= DOU_C;i++) {
m_d = ((i<<2) + 0.36954) * Math.sin((double)i);
}
}
public void doTest() {
testInt();
testDouble();
}
public static void main(String[] args) {
PerformanceTimer timer = new PerformanceTimer();
PerformTest test = null;
int j;
System.out.println("start test...");
timer.start();
for (j = 0;j < MAIN_C; j++) {
test = new PerformTest();
test.doTest();
test = null;
}
double duration = timer.end();
System.out.println("Program run druation: " + duration + " ms.");
}
}
3.2 实现时间测量的代码
public class PerformanceTimer {
private double freq;
private double startTime;
private double endTime;
public PerformanceTimer() {
this.freq = queryPerformanceFrequency();
}
private native double queryPerformanceFrequency();
private native double QueryPerformanceCounter();
public void start() {
this.startTime = QueryPerformanceCounter();
}
public double end() {
this.endTime = QueryPerformanceCounter();
double duration = (endTime - startTime) / freq * 1000;
return duration;
}
static {
try {
System.loadLibrary("PerformanceTimer");
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.3 实现时间测量的本地C++代码
省略javah生成的头文件,给出实现的源文件。
#include "stdafx.h"
#include "windows.h"
#include "PerformanceTimer.h"
JNIEXPORT jdouble JNICALL Java_PerformanceTimer_queryPerformanceFrequency
(JNIEnv *, jobject)
{
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
return (double)(freq.QuadPart);
}
JNIEXPORT jdouble JNICALL Java_PerformanceTimer_QueryPerformanceCounter
(JNIEnv *, jobject)
{
LARGE_INTEGER counter;
QueryPerformanceCounter(&counter);
return (double)(counter.QuadPart);
}
4 测试结果
我的软硬件环境:
硬件配置:AMD AthlonII X3 435 2.89GHz; 2GB DDR3内存;WD 500G硬盘;
软件环境:Windows7 旗舰版;Visual C++ 2008;SUN jdk1.6.0_21.
C++测试结果:
第一次 | 第二次 | 第三次 | 平均时间 | |
时间(单位:ms) | 21023.6 | 21003.5 | 21014.7 | 21013.9 |
Java测试结果:
第一次 | 第二次 | 第三次 | 平均时间 | |
时间(单位:ms) | 94369.4 | 94317.3 | 94347.2 | 94344.6 |
C++程序的性能竟是Java的3倍?这真的是他们之间真实的性能差距吗?我所用的测试方法是否科学呢?那么影响我们的Java程序的性能瓶颈在什么地方?