为什么这个简单的c++添加比同等的Java慢6倍?
why is this simple C++ addition 6 times slower than the equivalent Java?
stackoverflow用户你好,这是我第一个问题,如果我的表达方式有任何错误,请指出来,谢谢
我用Java和c++写了这个简单的计算函数
Java:long start = System.nanoTime();
long total = 0;
for (int i = 0; i < 2147483647; i++) {
total += i;
}
System.out.println(total);
System.out.println(System.nanoTime() - start);
c++: auto start = chrono::high_resolution_clock::now();
register long long total = 0;
for (register int i = 0; i < 2147483647; i++)
{
total += i;
}
cout << total << endl;
auto finish = chrono::high_resolution_clock::now();
cout << chrono::duration_cast<chrono::nanoseconds>(finish - start).count() << endl;
软件:——JDK8u11- Microsoft Visual c++编译器(2013)
结果:
Java:23058430059924684811096361110
C + +:23058430059924684816544374300
计算结果是相同的,这是很好的然而,打印的纳米时间显示Java程序需要1秒,而在c++中需要6秒来执行
我做Java已经有一段时间了,但是我是c++的新手,我的代码有什么问题吗?还是c++在简单计算方面比Java慢?
也,我在我的c++代码中使用了"register"关键字,希望它能带来性能改进,但执行时间根本没有区别,有人能解释一下吗?
编辑:我这里的错误是c++编译器设置没有优化,输出设置为x32,在应用/O2 WIN64并删除DEBUG后,程序只花了0.7秒来执行JDK默认对输出应用优化,然而vc++不是这样,它默认支持编译速度,不同的c++编译器的结果也不同,有些会在编译时间内计算循环的结果,导致极短的执行时间(大约5微秒)
注意:在适当的条件下,c++程序在这个简单的测试中会比Java表现得更好,但是我注意到许多运行时安全检查被跳过,违反了它作为"安全语言"的调试意图,我相信c++在大数组测试中甚至会比Java表现得更好,因为它没有绑定检查
在Linux/Debian/Sid/x86-64上使用OpenJDK 7
// file test.java
class Test {
public static void main(String[] args) {
long start = System.nanoTime();
long total = 0;
for (int i = 0; i < 2147483647; i++) {
total += i;
}
System.out.println(total);
System.out.println(System.nanoTime() - start);
}
}
和GCC 4.9的
// file test.cc
#include <iostream>
#include <chrono>
int main (int argc, char**argv) {
using namespace std;
auto start = chrono::high_resolution_clock::now();
long long total = 0;
for (int i = 0; i < 2147483647; i++)
{
total += i;
}
cout << total << endl;
auto finish = chrono::high_resolution_clock::now();
cout << chrono::duration_cast<chrono::nanoseconds>(finish - start).count()
<< endl;
}
然后用
编译并运行test.java
javac test.java
java Test
我得到了输出
2305843005992468481
774937152
使用优化编译test.cc
时
g++ -O2 -std=c++11 test.cc -o test-gcc
和运行./test-gcc
它跑得更快
2305843005992468481
40291
当然,没有优化g++ -std=c++11 test.cc -o test-gcc
,运行更慢
2305843005992468481
5208949116
通过使用g++ -O2 -fverbose-asm -S -std=c++11 test.cc
查看汇编代码,我看到编译器在编译时计算了结果:
.globl main
.type main, @function
main:
.LFB1530:
.cfi_startproc
pushq %rbx #
.cfi_def_cfa_offset 16
.cfi_offset 3, -16
call _ZNSt6chrono3_V212system_clock3nowEv #
movabsq $2305843005992468481, %rsi #,
movl $_ZSt4cout, %edi #,
movq %rax, %rbx #, start
call _ZNSo9_M_insertIxEERSoT_ #
movq %rax, %rdi # D.35007,
call _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ #
call _ZNSt6chrono3_V212system_clock3nowEv #
subq %rbx, %rax # start, D.35008
movl $_ZSt4cout, %edi #,
movq %rax, %rsi # D.35008, D.35008
call _ZNSo9_M_insertIlEERSoT_ #
movq %rax, %rdi # D.35007,
call _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_ #
xorl %eax, %eax #
popq %rbx #
.cfi_def_cfa_offset 8
ret
.cfi_endproc
.LFE1530:
.size main, .-main
所以你只需要在你的编译器中启用优化(或者切换到一个更好的编译器,比如GCC 4.9)
顺便说一句,Java的底层优化发生在JVM的JIT中。我不太了解JAVA,但我认为我不需要打开它们。我知道,在GCC上,你需要启用优化,当然是提前(例如与-O2
)
PS:在这个21世纪,我从未使用过任何微软编译器,所以我无法帮助你如何在它中启用优化。
最后,我不认为这样的微基准是重要的。基准测试然后优化您的实际应用程序。
耗时约0.6秒。592801000秒)在我的系统上,英特尔2600K, 3.40ghz,与MSVC Express 2013, 64位模式,标准发布构建。将计数移动到设置结束后,以不包括计数开销。
#include <iostream>
#include <chrono>
using namespace std;
int main()
{
auto start = chrono::high_resolution_clock::now();
register long long total = 0;
for (register int i = 0; i < 2147483647; i++)
{
total += i;
}
auto finish = chrono::high_resolution_clock::now();
cout << total << endl;
cout << chrono::duration_cast<chrono::nanoseconds>(finish - start).count() << endl;
return 0;
}
我认为要解释为什么C/c++总是比Java快,最简单的方法就是理解Java是如何工作的。
从一开始,Java就是为了促进跨平台软件而开发的。在Java之前,人们必须在每个机器家族上分别编译他们的程序。即使是现在,有了各种各样的硬件架构、公认的标准和操作系统,人们也无法绕过这个障碍。Java通过它的编译器和JVM来实现这一点。编译器应用它所能进行的任何优化,并将其汇编成Java字节码,字节码就像已编译的优化源代码的简写。但是,这个字节码还不能被处理器理解。
这就是Java虚拟机的由来。首先,JVM确定它正在哪个环境中运行,并加载适当的转换表。然后将字节码读入JVM,并在表中查找每个代码,并将其转换为环境的本机机器码,然后执行。
如你所知,每条指令都需要一点点时间。但是对于编译后的C/c++程序,它已经在适当的机器码中并立即执行。
有趣的提示-所有操作系统和大多数设备驱动程序都是用C编写的,出于性能原因。
- 我想知道长双倍和双倍之间的区别
- 在java中解决这段代码时面临循环中的问题
- 尝试用java代码编译和运行c++代码
- <T> 通过模板化运算符重载将 std::complex 乘以双倍
- 在这种情况下,java对象是否可以调用本机函数
- 如何编写一个使用n倍三元条件语句的C++布尔函数
- 在java中读取c++字节的位字段
- 为什么C++对链表中的下一个节点使用指针,而像 C# 或 Java 这样的语言只使用类 Node 的名称?
- 按值 C++ 返回时进行双倍移动
- 使用已使用 java 编码的 openssl 解码数据
- 求和 int 乘以双倍时的欠/过近似
- SWIG Java 在使用 -DSWIGWORDSIZE64 时将int64_t转换为 jlong
- Android Java USB for native cpp
- 在由Sublime文本3编译后在cmd上显示Java程序输出
- C++ equivalent to Java Map getOrDefault?
- C++ 中的 Java 样式枚举
- 为什么(我的)Java比C++快25倍
- Java使用数组的速度是C++中std::vector的8倍.我做错了什么
- Java比C快2+倍(作为C++的子集)
- 为什么这个简单的c++添加比同等的Java慢6倍?