我一直在用现有的 Java 代码开发一个 C++ 项目。我从同一个测试文件中读取了以下 C++ 代码和 Java 代码,该文件由数百万个整数组成。
C++:
int * arr = new int[len]; //len is larger than the largest int from the data
fill_n(arr, len, -1); //fill with -1
long loadFromIndex = 0;
struct stat sizeResults;
long size;
if (stat(fileSrc, &sizeResults) == 0) {
size = sizeResults.st_size; //here size would be ~551950000 for 552M test file
}
mmapFile = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, pageNum*pageSize);
long offset = loadFromIndex % pageSize;
while (offset < size) {
int i = htonl(*((int *)(mmapFile + offset)));
offset += sizeof(int);
int j = htonl(*((int *)(mmapFile + offset)));
offset += sizeof(int);
swapElem(i, j, arr);
}
return arr;
爪哇:
IntBuffer bb = srcFile.getChannel()
.map(MapMode.READ_ONLY, loadFromIndex, size)
.asIntBuffer().asReadOnlyBuffer();
while (bb.hasRemaining()) {
int i = bb.get();
int j = bb.get();
swapElem(i, j, arr); //arr is an int[] of the same size as the arr in C++ version, filled with -1
}
return arr;
void swapElem(arr)
在 C++ 和 Java 中是相同的。它比较和修改数组中的值,但原始代码有点长,无法在此处发布。出于测试目的,我将其替换为以下函数,因此循环不会是死代码:
void swapElem(int i, int j, int * arr){ // int[] in Java
arr[i] = j;
}
我假设 C++ 版本的性能应该优于 Java 版本,但测试给出了相反的结果——Java 代码几乎是 C++ 代码的两倍。有什么方法可以改进 C++ 代码吗?
我觉得可能mmapFile+offset
在 C++ 中重复了太多次,所以它是 O(n) 加法和 O(n) 加法offset+=sizeof(int)
,其中 n 是要读取的整数数。对于 Java 来说IntBuffer.get()
,它只是直接从缓冲区的索引中读取,所以除了缓冲区索引的 O(n) 递增 1 之外,不需要加法操作。因此,包括缓冲区索引的增量,C++ 需要 O(2n) 加法,而 Java 需要 O (n) 补充。当涉及到数百万个数据时,它可能会导致显着的性能差异。
按照这个想法,我修改了C++代码如下:
mmapBin = (char *)mmap(NULL, size, PROT_READ, MAP_SHARED, fd, pageNum*pageSize);
int len = size - loadFromIndex % pageSize;
char * offset = loadFromIndex % pageSize + mmapBin;
int index = 0;
while (index < len) {
int i = htonl(*((int *)(offset)));
offset += sizeof(int);
int j = htonl(*((int *)(offset)));
offset += sizeof(int);
index+=2*sizeof(int);
}
我认为会有轻微的性能提升,但没有。
谁能解释为什么 C++ 代码比 Java 代码运行得慢?谢谢。
更新:
我不得不道歉,当我说 -O2 不起作用时,我的结果出现了问题。我搞砸了 Makefile,所以 C++ 代码没有使用 -O2 重新编译。我已经更新了性能,使用 -O2 的 C++ 版本的性能优于 Java 版本。这可以解决问题,但如果有人想分享如何改进 C++ 代码,我会跟进。一般来说,我希望它比 Java 代码快 2 倍,但目前不是。谢谢大家的意见。
编译器:g++
标志:-Wall -c -O2
Java版本:1.8.0_05
文件大小:552MB,全部为 4 字节整数
处理器:2.53 GHz Intel Core 2 Duo
内存 4GB 1067 MHz DDR3
更新基准:
版本时间(毫秒)
C++:~1100
爪哇:~1400
C++(没有 while 循环):~35
Java(没有 while 循环):~40
我在这些代码之前有一些东西会导致〜35ms的性能(主要用-1填充数组),但这在这里并不重要。