Java和C++性能大比拼
用来运行Java语言的HotSpot VM主要是用C++语言来写的,所以我们在研究JDK时不得不去学习C++这门语言。C++和Java都是面向对象的语言,所以它们常被拿来做比较。本文将从性能的角度对比分析 Java 和 C++,粗略探讨两者在峰值速度、启动时间和启动性能以及内存利用率方面的差异。
## 1、峰值速度
Java的C2编译器能结合运行时的信息做推断和激进优化,其峰值性能并不比C++差。
C++有接近硬件的操作能力、执行效率和低级控制在性能要求极高的领域中占据一席之地。
所以两者并不能笼统的脱离实际来说性能的高低。不过我们倒是可以列举一些影响峰值速度的点来探讨。
### (1)内联
Java无论是C1还是C2编译器,内联都是重点的优化手段之一。Java类是动态加载的,HotSpot VM可以对这些新加载进来的类进行内联优化。不过目前的Java会在运行时调用native,在某些必要的情况下还会调用HotSpot VM内部的函数,这些是没办法内联的,这也是native开销大的原因之一。所以用纯Java写的一些算法也未必比调用native方法慢,比如在JDK8中并不支持Vector API,所以需要通过native来使用本地的向量化指令,但通过native调用时开销绝对不可以忽视。
Project Panama 的目标之一是
通过提供新的API来减少 JNI(Java Native Interface)的使用。
对于C++来说,动态链接库之间不能进行函数内联,否则就没办法让动态链接库单独进行更新和升级。另外动态分派中可被内联的情况也比较少。
### (2)动态分派
Java默认的方法都是动态分派,而C++需要通过virtual关键字专门指定,所以Java代码中的虚方法应该比C++中的多很多才对。
HotSpot VM中的虚函数能获取的信息更多,所以优化的手段也比较多,例如通过C2对receiver的类型推导、CHA(类型继承关系分析)以及运行时对receiver的type profile,这些可能让Java方法做单态内联、双态内联、多态内联、守护内联或做内联缓存优化。
C++是纯编译语言,虽然也有一些手段对虚函数做内联,但比起Java来,可用的内联信息更少,所以内联的效果肯定不如Java好。
### (3)值类型
Java不支持值类型,而C++支持。Java采用的是托管机制,其运行时动态编译编译和自动内存管理极大的降低了Java使用的门槛,不过Java不建议对底层的内存进行直接操作,所以也无法对底层的内存布局进行操作。有人将这称为导致Java和C语言之间性能差距的最后一个主要障碍。
当我们使用容器时,这种无值类型导致的性能差距可能更加明显,目前Java容器中的数组、链表不能直接保存结构,必须保存引用。所以Java数据结构和STL容器没法比。不过Java可以进行逃逸分析和标量替换,把许多临时对象的内存分配到栈上,这在一定程序上弥补了没有值类型的短板。
### (4)额外开销
HotSpot VM的托管技术让它有许多额外的开销,如GC和编译开销。在程序运行起来后,一切GC和编译相关的问题都是Java特有的,C++并不存在这种问题。
Java有许多额外检查,比如GC安全点检查、内存越界检查、类型检查等,这是我们为托管技术和安全性付出的必要代价。
Java中每个基本类型都有对应的包装类,这在一些上下文中需要频繁进行装箱和拆箱操作,C++并不存在这种问题。
总的来说,C++由于可操控性太强,只要代码写的足够好,额外开销是非常少的。对于Java来说,我们不得不做很多的让步。
## 2、启动时间和启动性能
Java虚拟机的动态特性让它可以根据需要对类进行加载。Java是面向对象的语言(Slogan:everything is object),类数量通常比较大且类加载还是IO操作,严重拖累了Java的启动速度,目前主要是通过CDS(后序的AppCDS、Dynamic CDS)来解决。
HotSpot VM为了照顾启动和峰值性能,默认采用的是分层编译,所以需要在系统运行一段时间后才能逐步由解释执行转化为解释执行 + 编译执行,这也意味着系统需要经过一段时间的预热才能达到性能巅峰
C++ 是静态编译的语言,代码在编译时直接生成机器码,启动即巅峰,其启动时间和启动性能应该要完胜Java才对。
不过随着云原生的到来,Java的启动时间慢和启动性能低的缺点被放大,Java开发者也在努力解决这些问题。例如:
(1)通过CDS来优化类加载的速度,这样可以显著减少类加载、解析和初始化的时间
(2)JDK 9开始提供工具jaotc,同时GraalVM的Native Image都是可以通过静态编译,极大地提升服务的启动速度的方式
(3)CRaC(协调恢复检查点)可以把预热后的 JVM 保存下来,然后快速启动。也就是快照保存和恢复。
更多的启动相关的优化可以看看Project Leyden项目,这个项目专注于缩短 Java 应用程序的启动时间。
另外,Azul JDK的Platform Prime版本提供了Ready Now和Ready Now Orchestrator作为解决 Java 预热问题的解决方案,阿里也在启动上做了一些优化和探索。
## 3、内存利用率
之前我写过 “历数Java虚拟机GC的种种缺点" 文章,文章中提到过额外分配和浪费的内存,如To Survivor不能用来进行内存分配,卡表需要额外的内存,Java的延迟回收让它白白点用了一段时间内存。
C++具有接近硬件的操作能力,以HotSpot VM为例,它通过重载new和delete运算符、通过C++中的资源获取即初始化技术将资源的分配和释放与对象的生命周期进行绑定等手段,实现了对内存的精确控制。
由于Java对内存的利用率低,所以和C++相比,它的峰值内存和平时内存占用都会显著高于C++程序。
Java的物理内存归还,Lilliput缩小Java对象头、CDS让多个虚拟机共享类元数据以及Valhalla项目对Java值类型的支持,都能够提高Java内存的利用率,减少浪费。
更多文章可访问:[JDK源码剖析网](http://hotspotvm.cn)
<img src="https://img2024.cnblogs.com/blog/1236123/202504/1236123-20250424100503675-351126910.png" width="550" height="200">
Java和C++性能大比拼的更多相关文章
- lua、groovy嵌入到java中的性能对比(转)
lua和groovy都是可以嵌入到java中的脚本语言.lua以高性能著称,与C/C++在游戏开放中有较多使用,groovy是一个基于Java虚拟机(JVM)的敏捷动态语言,在jvm下有着不错的性能. ...
- 2017年的golang、python、php、c++、c、java、Nodejs性能对比(golang python php c++ java Nodejs Performance)
2017年的golang.python.php.c++.c.java.Nodejs性能对比 本人在PHP/C++/Go/Py时,突发奇想,想把最近主流的编程语言性能作个简单的比较, 至于怎么比,还是不 ...
- 性能调优之Java系统级性能监控及优化
性能调优之Java系统级性能监控及优化 对于性能调优而言,通常我们需要经过以下三个步骤:1,性能监控:2,性能剖析:3,性能调优 性能调优:通过分析影响Application性能问题根源,进行优化 ...
- 2017年的golang、python、php、c++、c、java、Nodejs性能对比[续]
2017年的golang.python.php.c++.c.java.Nodejs性能对比[续] 最近忙,这个话题放了几天,今天来个续集. 上篇传送门: 2017年的golang.python.p ...
- Java应用常用性能分析工具
Java应用常用性能分析工具 好的工具有能有效改善和提高工作效率或加速分析问题的进度,笔者将从事Java工作中常用的性能工具和大家分享下,如果感觉有用记得投一票哦,如果你有好的工具也可以分享给我 工具 ...
- JProfiler 解决 Java 服务器的性能跟踪
作者:徐建祥(netpirate@gmail.com) 时间: 2006/01/05 来自:http://www.anymobile.org 1.摘要......................... ...
- 用于快速排查Java的CPU性能问题(top us值过高)
转载于GIT路径 https://github.com/oldratlee/useful-scripts/blob/master/docs/java.md#beer-show-busy-java-th ...
- Java-Runoob-高级教程-实例-字符串:11. Java 实例 - 字符串性能比较测试
ylbtech-Java-Runoob-高级教程-实例-字符串:11. Java 实例 - 字符串性能比较测试 1.返回顶部 1. Java 实例 - 字符串性能比较测试 Java 实例 以下实例演 ...
- Java MVC框架性能比较
Java MVC框架性能比较 - by zvane 现在各种MVC框架很多,各框架的优缺点网络上也有很多的参考文章,但介绍各框架性能方面差别的文章却不多,本人在项目开发中,感觉到采用了struts2框 ...
- 使用Memcached改进Java企业级应用性能:架构和设置
Memcached由Danga Interactive开发.用来提升LiveJournal.com站点性能. Memcached分布式架构支持众多的社交网络应用,Twitter.Facebook还有W ...
随机推荐
- 在 Intel Ultra AI PC 设备上使用 OpenVINO™ C# API本地部署YOLOv11与YOLOv12
最新的英特尔 酷睿 Ultra 处理器(第二代)让我们能够在台式机.移动设备和边缘中实现大多数 AI 体验,将 AI 加速提升到新水平,在 AI 时代为边缘计算提供动力.英特尔 酷睿 Ultra ...
- ABAQUS-循环对称条件的详解
概括 anlysis of model that exhibit cyclic symmetry 循环对称分析技术用于Standard求解器. makes it possible to analyze ...
- 【Python】批量提取Fibersim xml文件中的节点网格数据
程序功能: 输入需求: fibersim导出的ply 的xml文件,可以很多个也没问题.但名字要有规律,不然没法循环读写.比如我自己用的就是x1.xml.x2.xml.Y1.xml......的文件名 ...
- qa 工作
1.定流程--监控参照规范(cmmi,公司自己的,scrum[例会.启动会])--产出物报告 (项目维度)-配置--经盈.财务 2.培训组织-组织讲师(知识库).外部拓展
- leetcode两数之和变种(找出所有满足总和的两个数)
偶尔看到leetcode 的两数之和,但是之前遇到过两数之和的变种,之前一开始想不出来,后面看了别人的题解才想到解法,这里记录一下. 题目描述: 原leetcode题目描述 给定一个整数数组 nums ...
- mysql frm、MYD、MYI数据文件恢复,导入MySQL中
前言 .frm..MYI..MYD 文件分别是 MySQL 的 MyISAM存储引擎存储的表结构.索引.数据文件. 简单方法恢复数据 .frm..MYI..MYD文件如果直接以文本打开,全部会以二进制 ...
- wps时间戳转换成日期
第一步 打开WPS表格,选择空表格 第二步 右击选择"设置单元格格式" 第三步 选择"日期",然后选择需要的日期类型 第四步 然后在表格里,输入公式 =(D2/ ...
- 搭建自己的OCR服务,第二步:PaddleOCR环境安装
PaddleOCR环境安装,遇到了很多问题,根据系统不同问题也不同,不要盲目看别人的教程,有的教程也过时了,根据实际情况自己调整. 我这边目前是使用windows 10系统+CPU + python ...
- 找到占用磁盘最多的文件或目录,可以使用du和sort
想要找到占用磁盘最多的文件或目录,可以使用du和sort命令: du -h /path/to/directory | sort -rh | head -n 10 其中: du -h /path/t ...
- DEV插件--Spreadsheet1电子表格
常用操作Spreadsheet常用属性标题栏是否可见 Spreadsheet1.TitleBar.Visible=true标题栏背景颜色 Spreadsheet1.TitleBar.Interior. ...