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

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

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

  1. 大量小对象

  2. 多种类型

  3. 代码量大

缺一不可。

这类任务说到底就是模拟。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点:

  1. 大量小对象

  2. 多种类型

  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++的内存布局上下功夫。

转载于:https://blog.51cto.com/13904503/2286309

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

  1. java计算何时赶超_网上说 Java 的性能已经达到甚至超过 C++,是真的吗?

    求一个完成中值滤波的纯JAVA代码.我手里正好有一个C++的中值滤波代码,想对比下两者究竟差距多大. @圆胖肿 可否写一个JAVA程序来佐证下你的观点呢? 我这面的C++代码,对一张5184*3456 ...

  2. 如何用JNI技术提高Java的性能详解

    阻碍Java获得广泛应用的一个主要因素是Java程序的运行效率.Java是介于解释型和编译型之间的一种语言,同样的程序,如果用编译型语言C来实现,其运行速度一般要比Java快一倍以上.Java具有平台 ...

  3. 百万并发中间件系统的内核设计看Java并发性能优化

    " 这篇文章,给大家聊聊一个百万级并发的中间件系统的内核代码里的锁性能优化. 很多同学都对Java并发编程很感兴趣,学习了很多相关的技术和知识.比如volatile.Atomic.synch ...

  4. java代码统计收藏量_干货收藏 | 35个Java 代码性能优化总结(上)

    原标题:干货收藏 | 35个Java 代码性能优化总结(上) 前言 代码优化,一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这 ...

  5. Java日志性能那些事

    在任何系统中,日志都是非常重要的组成部分,它是反映系统运行情况的重要依据,也是排查问题时的必要线索.绝大多数人都认可日志的重要性,但是又有多少人仔细想过该怎么打日志,日志对性能的影响究竟有多大呢?今天 ...

  6. Java中性能优化的35种方法汇总

    原文地址:http://www.jb51.net/article/102831.htm 前言 对程序员们来说,代码优化是一个很重要的课题.可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于 ...

  7. java锁性能对比_提高Java的锁性能

    java锁性能对比 Plumbr是唯一可以通过解释应用程序性能数据来自动检测Java性能问题根本原因的解决方案. 几个月前,我们在Plumbr中引入了锁定线程检测之后,我们开始收到类似于"嘿 ...

  8. 一个牛人给JAVA初学者的建议。虽然岁月漫长,但仍值得等待

    给初学者之一:浅谈java及应用 学java不知不觉也已经三年了 从不知java为何物到现在一个小小的j2ee项目经理 虽说不上此道高手,大概也算有点斤两了吧 每次上网,泡bbs逛论坛,没少去java ...

  9. Java日志性能那些事(转)

    在任何系统中,日志都是非常重要的组成部分,它是反映系统运行情况的重要依据,也是排查问题时的必要线索.绝大多数人都认可日志的重要性,但是又有多少人仔细想过该怎么打日志,日志对性能的影响究竟有多大呢?今天 ...

最新文章

  1. 小姐姐都能看懂的Happens-before规则,你还愣住了?
  2. 绘制E—R图(详细)
  3. 【深度学习】caffe 中的一些参数介绍
  4. java添加不了源代码,JAVA初学者的一些问题
  5. JZOJ 5386. 【NOIP2017提高A组模拟9.23】碎
  6. 语音识别(三)——声学模型, 解码器技术
  7. 如何促合作共赢?技术人的一点经验分享
  8. redirect重定向后https变成了http如何解决
  9. 返回List的分页方法
  10. 关于虚函数重载遇到的怪问题 -- 为什么经常调用了基类的函数
  11. WINDOWS.H already included.MFC apps must not #include windows.h
  12. 中国互联网十大骨干网有哪些?了解互联网的真实网络结构
  13. 非形式逻辑(04)因果关系和推理
  14. fabric2.0 概念, peer、账本和排序服务
  15. Ant Design - Authorized
  16. apollo之集群部署(二)
  17. 青岛大学计算机专业春考,青岛大学春季高考分数线2020
  18. maya linux 安装教程视频,在 Ubuntu 上安装 Maya 2020 - Flame.VIP
  19. 从平台到中台 | Elasticsearch 在蚂蚁金服的实践经验
  20. AOP 主要应用场景

热门文章

  1. Symbian开发系列 - 入门篇
  2. python3 的 round 函数的 练习
  3. 定时调度模块:sched
  4. JSP+Servlet基础一
  5. 嵌入式实现 微信网页版 群发信息。
  6. Nginx负载均衡之TCP端口高可用(二)
  7. 手把手教你如何新建scrapy爬虫框架的第一个项目(下)
  8. 【跃迁之路】【554天】程序员高效学习方法论探索系列(实验阶段311-2018.08.13)...
  9. Javascript闭包和闭包的几种写法及用途
  10. Linux下设置进程使用指定核的CPU