6. 晚期编译优化 晚期编译优化主要是在运行时做的一些优化手段。 ,所花费的时间可能更长;而且想要编译出优化程度更高的代码,解释器可能还要替编译器收集性能监控信息,这对解释执行的速度也有影响。 ,将字节码编译为本地代码,进行简单、可靠的优化,如有必要将加入性能监控的逻辑 第2层:也称为C2编译,也是将字节码编译为本地代码,但是会启用一些编译耗时较长的优化,甚至会根据性能监控信息进行一些不可靠的激进优化 上分离寄存器,并在LIR上做窥孔(Peephole)优化,然后产生机器代码 Server Compiler是专门面向服务端的典型应用并为服务端的性能配置特别调整过的编译器,它会执行所有经典的优化动作。 由于java语言中访问数组元素时,系统将会自动进行上下界的范围检查,这必定会造成性能负担。为了安全,数组边界检查是必须做的,但数组边界检查是否必须一次不漏的执行则是可以“商量”的事情。
使用阶段,实例化对象和调用方法等,Class对象在JVM中一直有效,直到JVM退出。6. 卸载阶段,不会主动卸载Class对象。但是如果一个类的所有实例都被回收,对应的Class对象有可能被卸载。 标记压缩需要移动可达对象,额外付出性能代价,但可以减少内存碎片。垃圾回收器的基本原理是什么?垃圾回收器可以马上回啊收内存吗?有什么办法主动通知虚拟机进行垃圾回收?垃圾回收器的基本原理:1. 垃圾收集需要付出较高的性能开销,频繁回收会严重影响程序性能。2. 回收内存需要STW(Stop The World),停止用户线程,如果回收太频繁会影响程序响应性。3. 6. 映射使用不当:像Map等映射如果keyDisappear后value没有释放,会产生内存泄漏。解决办法:1. 及时关闭外部资源:如数据库连接、网络连接、文件流等。2. 6. 映射中使用WeakHashMap:如果key可能消失,可以使用WeakHashMap,其entry会自动gc,防止内存泄漏。
2、JVM字节码 前面我们通过tomcat本身的参数以及jvm的参数对tomcat做了优化,其实要想将应用程 序跑的更快、效率更高,除了对tomcat容器以及jvm优化外,应用程序代码本身如果写的效率不高的 ,那么也是不行的,所以,对于程序本身的优化也就很重要了。 .#29 // cn/itcast/jvm/Test2.method1: ()V #5 = Methodref #2.#30 // cn/itcast/jvm/Test2.method2: ()V #6 f87a55446b8b6cd88b6e54bd5edcc9dc Compiled from "Test4.java" public class cn.itcast.jvm.Test4 minor version 可以更好的对我们的代码做优化。让程序执行效率更高。
JVM常用指令 ~~~shell 指令码 助记符 说明 0x00 nop 什么都不做 0x01 aconst_null 将null推送至栈顶 0x02 iconst_m1 将int型-1推送至栈顶 0x67 dsub 将栈顶两double型数值相减并将结果压入栈顶 0x68 imul 将栈顶两int型数值相乘并将结果压入栈顶 0x69 lmul 将栈顶两long型数值相乘并将结果压入栈顶 0x6a fmul 将栈顶两float型数值相乘并将结果压入栈顶 0x6b dmul 将栈顶两double型数值相乘并将结果压入栈顶 0x6c idiv 将栈顶两int型数值相除并将结果压入栈顶 0x6d ldiv 将栈顶两long型数值相除并将结果压入栈顶 0x6e fdiv 将栈顶两float型数值相除并将结果压入栈顶 0x6f ddiv 将栈顶两double型数值相除并将结果压入栈顶 0x70 int型数值大小,当结果大于0时跳转 0xa4 if_icmple 比较栈顶两int型数值大小,当结果小于等于0时跳转 0xa5 if_acmpeq 比较栈顶两引用型数值,当结果相等时跳转 0xa6
深入了解性能优化 7.1 影响系统性能的方方面面 影响系统性能的因素有很多,以下列举了常见的一些系统性能优化的方向: 7.2 常用的性能评价和测试指标 响应时间 提交请求和返回该请求的响应之间使用的时间 7.3 常用的性能优化手段 对于系统的性能调优,总体上从如下三个方面入手: 前端优化 应用服务性能优化 存储性能优化 但是无论怎么优化,总原则就是: 避免过早优化,优化的前提是基本功能完成且测试通过; 进行系统性能测试,需要通过性能测试来确定性能,不能主观臆测; 寻找系统瓶颈,分而治之,逐步优化。 前端优化 浏览器/App 减少请求数; 使用客户端缓冲; 启用压缩 资源文件加载顺序 减少Cookie传输 CDN加速 反向代理缓存 WEB组件分离 应用服务性能优化 1. JVM调优 GC调优的方向:GC的时间够小,GC的次数够少 大多数的Java应用不需要GC调优,大部分需要GC调优的,不是参数问题,是代码问题 GC调优是最后手段。
早期编译优化 早期编译优化主要指编译期进行的优化。 javac这类编译器对代码的运行效率几乎没有任何优化措施,但javac做了许多针对java语言代码过程的优化措施来改善程序员的编码风格和提高编码效率,java许多的语法特性都是靠编译器的语法糖来实现的。 because return type of method is Integer 自动装箱的弊端, 自动装箱有一个问题,那就是在一个循环中进行自动装箱操作的时候,如下面的例子就会创建多余的对象,影响程序的性能
collection在垃圾回收的时候使用的内存 JIT optimization使用的内存 java程序的Off-heap所使用的内存 java程序的Metaspace所使用的内存 JNI Code所占用的内存 jvm Max memory = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss] 猜测在设置jvm启动参数的时候 -Xmx的这个值一般要小于docker 限制内存数,经过生产环境实验 -Xmx:docker的比例为 2/3 - 3/4, 一般生产环境都是用的sunjdk,所以建议xmx与xms设置一样大 避免JVM在运行过程中向OS申请内存 延后启动后首次 GC的发生时机 减少启动初期的GC次数 避免动态调整jvm堆大小 2、xmn或者maxnewSize设置 xmn设置年轻代大小。
前言 入门JVM垃圾回收机制后,接下来可以学习性能调优了。主要有两部分内容: JDK工具的使用。 调优策略。 用法如下: jps [-option] [hostid] 选项 作用 q 只输出LVMID,省略主类的名称 m 输出main method的参数 l 输出完全的包名,应用主类名,jar的完全路径名 v 输出jvm gcnew 输出新生代空间的GC性能数据。 gcnewcapacity 输出新生代空间的大小的统计数据。 gcold 输出老年代空间的GC性能数据。 比如: jstat -gc 28389 1s 每隔1秒输出一次JVM运行信息: ? ? ? ? ? ? jmap 生成堆存储快照,使用方式: ? ? -Xms:启动JVM时的堆内存空间。 -Xmx:堆内存最大限制。 设定新生代大小。 新生代不宜太小,否则会有大量对象涌入老年代。 -XX:NewRatio:新生代和老年代的占比。
3、jvm的内存模型 jvm的内存模型在1.7和1.8有较大的区别,虽然本套课程是以1.8为例进行讲解,但是我们 也是需要对1.7的内存模型有所了解,所以接下里,我们将先学习1.7再学习1.8的内存模型 Survivor区,其中, Survivor区间中,某一时刻只有其中一个是被使用的,另外一个留做垃圾收集时复制对象用,在Eden区间变满的时候, GC就会将存活的对象移到空闲的Survivor区间中,根据JVM 翻译: 移除永久代是为融合HotSpot JVM与 JRockit VM而做出的努力,因为JRockit没有永久代, 不需要配置永久代。
综上所述,除了作为一个程序员,精益求精是基本要求之外,深入了解GC机制让我们的代码更有效率,尤其是在构建大型程序时,GC直接影响着内存优化和运行速度。 然而,后者将会严重影响代码的性能,因为一般每一次显式的调用 system.gc() 都会停止所有响应,去检查内存中是否有可回收的对象。这会对程序的正常运行造成极大的威胁。 另外,调用该方法并不能保证 JVM 立即进行垃圾回收,仅仅是通知 JVM 要进行垃圾回收了,具体回收与否完全由 JVM 决定。这样做是费力不讨好。 XX:+UseParallelOldGC –XX:ParallelGCThreads=8 运行代码,输出如下: clean map 8798 cost time=1998 ---- 5 JAVA性能优化 真正影响JAVA程序性能的,就是碎片化。碎片是JAVA堆内存中的空闲空间,可能是TLAB剩余空间,也可能是被释放掉的具有较长生命周期的小对象占用的空间。
在Java应用开发中,JVM性能优化是提升系统稳定性和响应速度的关键环节。以下是一些常见的JVM性能优化方案:1. 元空间配置:使用-XX:MetaspaceSize和-XX:MaxMetaspaceSize控制元空间大小,避免动态扩展导致的性能波动。 Analyzer Tool)、YourKit、ArthasGC日志分析:通过-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log记录GC日志6. ,需要结合具体应用场景,通过监控分析找到性能瓶颈,有针对性地进行调整。 建议采用渐进式优化策略,每次只调整少数参数并对比效果。
2、jvm的运行参数 在jvm中有很多的参数可以进行设置,这样可以让jvm在各种环境中都能够高效的运行。绝大部分的参数保持默认即可。 JVM在启动的时候会根据硬件和操作系统自动选择使用Server还是Client类型的 JVM。 32位操作系统 如果是Windows系统,不论硬件配置如何,都默认使用Client类型的JVM。 -Xcomp参数与它(-Xint)正好相反,JVM在第一次使用时会把所有的字节码编译成本地代码,从而带来最大程度的优化。 然而,很多应用在使用-Xcomp也会有一些性能损失,当然这比使用-Xint损失的少,原因是xcomp没有让JVM启用JIT编译器的全部功能。 2.6.2、查看正在运行的jvm参数 如果想要查看正在运行的jvm就需要借助于jinfo命令查看。 首先,启动一个tomcat用于测试,来观察下运行的jvm参数。 ? 访问成功: ?
优化Java代码需要理解Java中不同元素是如何交互的,以及与操作系统是如何交互的,下面五个技巧帮助你分析和优化代码。 性能优化依赖于许多情况,比如垃圾回收,虚拟机和底层操作系统设置。 有许多工具帮助开发者分析和优化。 通过一下网址可以了解学习Java源码分析和优化工具 https://dzone.com/articles/java-tools-source-code 下面是五个技巧建议: 1.微调垃圾回收机制 挖掘到你的应用真正性能是很难的 一旦你比较满意调校结果,就要停止调校,不要再试验其他优化方式,确保平均处理时间符合你的大概要求。 另外你需要理解在运行期间的性能影响点,单次数据库处理如果有减慢需要值得注意。 5.使用优化函数 几种有助提升性能的函数: (1).使用StringBuilder而不是+操作符 (2).避免使用 iterator(). (3).最大化利用stack栈 (4).避免正则表达式,使用Apache
新的版本通常有更好的性能优化。 因没有足够内存避免 swapping 总是关注你服务器的交换(swapping)活动。 这是因为交换器导致 JVM 在进行 Garbage Collection 的时候暂停,这个将会导致内部节点的通信中断,而这个通信又是节点进行同步所需要的。 我们推荐你使用你熟悉的数据库,因为你能够更好的对数据库进行维护,这个可能相对你不熟悉的数据库来说,能更好的让你对数据库的性能进行优化。 如果数据库查询命中率明显的不同,那么你需要考虑对数据库运行状态收集和优化。针对你数据库的版本不同,优化的版本和方向也会不同。 一些插件我们已经知道能够对系统性能造成影响并最终导致 Confluence 的崩溃。 https://www.cwiki.us/display/CONF6ZH/Performance+Tuning
垃圾回收时间不应该超过整体时间的1% ---- JVM微调调试方法 配置JVM的JAVA_OPTS参数 –verbosegc 观察Full GC的信息输出: [Full GC $before->$after ---- JVM优化参数 JAVA_OPTS="$JAVA_OPTS -verbose:gc -XX:+PrintGCDetails -XX:+PrintTenuringDistribution CMSIncrementalMode -XX:CMSInitiatingOccupancyFraction=80 -XX:+CMSClassUnloadingEnabled 最大新生代GC暂停时间是250毫秒,在这个基础上JVM JVM推荐设置 Heap size Total GC pauses GC暂停 Throughput吞吐量 -Xmx300m 207.48s 92.25% -Xmx384m 54.13s 97.97% -
GC监控是为了鉴别JVM是否在高效地执行GC,以及是否有必要进行额外的性能调优。基于以上信息,我们可以修改应用程序或者调整GC算法(GC优化)。 全称“Java Virtual Machine statistics monitoring tool”,主要利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size 利用JVM内建的指令对Java应用程序的资源和性能进行实时的命令行的监控,包括了对Heap size和垃圾回收状况的监控。查看GC操作的信息,类装载操作的信息以及运行时编译器操作的信息。 5.也可以使用 jmap -dump:format=b,file=<fileName>命令将堆信息保存到一个文件中,再借助jhat命令查看详细内容 6.在内存出现泄露、溢出或者其它前提条件下,建议多dump 在 NIO里采用了新的机制,编写的服务器程序的性能和可扩展性都得到提高。
---- JVM性能的人为问题 关键原因是:没有正确处理好对象的生命周期。 需要从需求中找出存在自然边界的业务对象,将其对应落实到内存中,成为内存模型In-memory Domain Model。 4.静态属性意味着全局变量,生命周期和JVM一致。JVM属于技术边界,静态只能用于技术边界内工具性质使用,不能用作业务。 JVM性能优化 1、内存微调优化 2、锁争夺微调: 多线程 不变性 单写原则 Actor Disrupotor 3、CPU使用率微调 4、I/O 微调 ---- 内存微调优化 这些都根据情况调整启动JVM的设置。 使用 Adaptive让JVM自动划分新生代和老生代。 Xms1G -XX:NewSize=512M (OldGen at least 2G) 3、Xmx4G -Xms2G -XX:NewSize=1G (OldGen at least 2.5G) 4、-Xmx6G
JVM整体结构 ? 堆 线程共享的区域,也是垃圾回收器要收集的区域,这地方主要保存用户创建的对象。例如 new User(),这个对象是保存在堆上面的。 了解jvm的同学应该都知道,堆其实是分为新老年代的,这主要是为了进行垃圾回收而设计的一种结构 ? 新老年代相关jvm参数 -XX:NewRatio 设置新老年代比例,如-XX:NewRatio=5 代表 新老年代比例为1:5,新生代占用堆内存的1/6,老年代占用5/6;jvm默认新老年代为1:2;需要注意的是如果程序启动指定了 解释模式 执行一行字节码就编译成一行机器码执行 特点:使用解释模式,JVM启动速度快,但是执行执行命令慢,需要一行一行进行编译 编译模式 先将所有字节码全部编译为机器码,然后一次性加载所有机器码执行 特点 ,减少重复编译,从而提高代码执行效率,这个也是JVM默认采用的编译模式,这个就是JIT(即时编译技术) ?
对于 JVM 调优,首先应该明确,full gc/minor gc,都会导致JVM的工作线程停止工作,即stop the world。 1. 但是如果在某些情况下cache操作内存不是很紧张,而task的算子中创建的对象很多,Execution内存又相对较小,这回导致频繁的minor gc,甚至于频繁的full gc,进而导致Spark频繁的停止工作,性能影响会很大 find,executor lost,task lost,out of memory等错误,此时,就可以考虑调节一下Executor的堆外内存,也就可以避免报错,与此同时,堆外内存调节的比较大的时候,对于性能来讲 Executor堆外内存的配置需要在spark-submit脚本里配置, --conf spark.executor.memoryOverhead=2048 以上参数配置完成后,会避免掉某些JVM OOM 的异常问题,同时,可以提升整体 Spark 作业的性能。
1.什么是JVM的Minor GC? JVM的MinorGC为新生代GC,触发时处理步骤如下: 1. 扫描出在新生代中存活的对象; 2. 2.什么是JVM的Full GC? 对新生代、旧生代及持久代都进行GC,Full GC被触发时处理步骤为: 1. 3.什么情况下会触发JVM的Full GC? 例如程序第一次触发Minor GC后,有6MB的对象晋升到旧生代,那么当下一次Minor GC发生时,首先检查旧生代的剩余空间是否大于6MB,如果小于6MB,则执行FullGC。 当新生代采用PS GC时,方式稍有不同,PS GC是在Minor GC后也会检查,例如上面的例子中第一次Minor GC后,PS GC会检查此时旧生代的剩余空间是否大于6MB,如小于,则触发对旧生代的回收