ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

部分人说 Java 的性能已经达到甚至超过 C++,是真的吗?

2022-11-02 13:01:03  阅读:284  来源: 互联网

标签:javaJDK java 虚拟机 布局 数据 代码 程序 面试 题目


好多Java程序员都说由于JIT技术的引入,Java的性能已经和C++一样了,而且Java的开发效率极高,可以省下60%的时间。请问事实真的是这样吗?我平常也都在写这两个语言,但是因为开发的软件的复杂度不大,并没有感觉到性能和开发效率有太大的差异,如果真的如那些Java程序员所说的那样,为什么主流的游戏引擎都不用Java实现呢?而且教育版的Minecraft为什么要用C++重写呢?

游戏/CAD本来就是C++的核心阵地,特别难被其它语言取代。(科学计算/网络服务方面的强势则更多是惯性使然)在这个场景下Java和C++有明显的性能差距,不代表别的场景下两者性能不能接近。

这类场景的特点是什么呢?操作一大堆各种类型小对象的复杂代码。

大量小对象

多种类型

代码量大

缺一不可。

这类任务说到底就是模拟。Bjarne Stroustrup创造C++就是为了做模拟,并非偶然。

Memory wall是越来越高的。Memory is the new disk. 对于这类任务,不是说你JIT生成了理论上最少cycle数的代码,性能就比肩C/C++了,还要看对象的内存布局。内存布局不能和C/C++一样紧凑的话,可能从起跑线上就已经输了。

比如最简单的对象:

struct Point {

float x;

float y;

float z;

};

C/C++的内存布局:

<img src="https://pic1.zhimg.com/994bbb21a2c2dff43a30fc68d8877bc0_b.png" data-rawwidth="180" data-rawheight="220" class="content_image" width="180">

不可能比这更紧凑了。

再看Java(当然,与JVM具体实现相关):

<img src="https://pic2.zhimg.com/c56ed90999816e9846719d3a653dd095_b.png" data-rawwidth="402" data-rawheight="272" class="content_image" width="402">

多出这12 bytes可能就是内循环能不能放进L1 cache,或者对象能不能放进一个cache line的区别(后者具体到这个例子里没问题)。

Java毕竟还有primitive types。换成一些脚本语言,比如Python,每个float还有自己的header,那更没法看了。这是一个struct。如果有嵌套的情况:

struct Line {

struct Point begin;

struct Point end;

};

C/C++:

<img src="https://pic4.zhimg.com/7e9c336be9085a3169b67ee73d0afccf_b.png" data-rawwidth="399" data-rawheight="373" class="content_image" width="399">

Java:

<img src="https://pic2.zhimg.com/d71be36c2b1cfe7370fb231619295cd5_b.png" data-rawwidth="807" data-rawheight="555" class="origin_image zh-lightbox-thumb" width="807" data-original="https://pic2.zhimg.com/d71be36c2b1cfe7370fb231619295cd5_r.jpg">

这就不只是多几个byte,还多了间址,有数据依赖。

再看数组:

struct Point v[100];

C/C++:

<img src="https://pic2.zhimg.com/7045a1b9b3078456f0edf0e1efbc5149_b.png" data-rawwidth="401" data-rawheight="423" class="content_image" width="401">

Java:

<img src="https://pic1.zhimg.com/1ebd05c48c441883202c772746ede3a8_b.png" data-rawwidth="869" data-rawheight="561" class="origin_image zh-lightbox-thumb" width="869" data-original="https://pic1.zhimg.com/1ebd05c48c441883202c772746ede3a8_r.jpg">

内存访问局部性差距比较大。回头看前面说的3点:

大量小对象

多种类型

代码量大

如果对象都是大块连续内存,比如1MB的文本块,那么object header和间址的开销就被吸收了。

如果不是类型多和代码量大,那么你不太需要C++的抽象能力,完全可以用C。

另一方面,如果类型少,你即使用Java也可以绕过语言的类型系统自己控制布局。比如Hive根本上只有Record一种对象重要,它就可以让Record大部分时间以序列化之后的形式作为内存中的一段连续字节,回避了以上各种开销。

而如果任务同时具备以上3个特点,那么对于Java(和其它高级语言),如果不能把内循环访问的对象的内存布局优化到和C/C++基本一致,那么即使JIT再先进,性能也难以接近C/C++。

所以你看到microbenchmark里JIT表现出色的往往是Fibonacci这种只涉及int和int[]的短循环/递归。别说Java JIT了,就是Python,PyPy在这类benchmark上也表现不错。然而就此推测PyPy开发游戏引擎的表现就不太靠谱。

对于JVM来说,Project Valhalla和Azul Systems的ObjectLayout似乎都在程序员手动生成近似C/C++的内存布局上下功夫。

好多Java程序员都说由于JIT技术的引入,Java的性能已经和C++一样了,而且Java的开发效率极高,可以省下60%的时间。请问事实真的是这样吗?我平常也都在写这两个语言,但是因为开发的软件的复杂度不大,并没有感觉到性能和开发效率有太大的差异,如果真的如那些Java程序员所说的那样,为什么主流的游戏引擎都不用Java实现呢?而且教育版的Minecraft为什么要用C++重写呢? 游戏/CAD本来就是C++的核心阵地,特别难被其它语言取代。(科学计算/网络服务方面的强势则更多是惯性使然)在这个场景下Java和C++有明显的性能差距,不代表别的场景下两者性能不能接近。 这类场景的特点是什么呢?操作一大堆各种类型小对象的复杂代码。 大量小对象 多种类型 代码量大 缺一不可。 这类任务说到底就是模拟。Bjarne Stroustrup创造C++就是为了做模拟,并非偶然。 Memory wall是越来越高的。Memory is the new disk. 对于这类任务,不是说你JIT生成了理论上最少cycle数的代码,性能就比肩C/C++了,还要看对象的内存布局。内存布局不能和C/C++一样紧凑的话,可能从起跑线上就已经输了。 比如最简单的对象: struct Point { float x; float y; float z; }; C/C++的内存布局

标签:javaJDK,java,虚拟机,布局,数据,代码,程序,面试,题目
来源:

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有