织梦网站如何播放mp4,WordPress更该主题,汕头企业自助建站,百度关键词查询工具免费此笔记来至于 黑马程序员 内存调优
内存溢出和内存泄漏
内存泄漏#xff08;memory leak#xff09;#xff1a;在Java中如果不再使用一个对象#xff0c;但是该对象依然在 GC ROOT 的引用链上#xff0c;这个对象就不会被垃圾回收器回收#xff0c;这种情况就称之为内…此笔记来至于 黑马程序员 内存调优
内存溢出和内存泄漏
内存泄漏memory leak在Java中如果不再使用一个对象但是该对象依然在 GC ROOT 的引用链上这个对象就不会被垃圾回收器回收这种情况就称之为内存泄漏。内存泄漏绝大多数情况都是由堆内存泄漏引起的所以后续没有特别说明则讨论的都是堆内存泄漏。少量的内存泄漏可以容忍但是如果发生持续的内存泄漏就像滚雪球雪球越滚越大不管有多大的内存迟早会被消耗完最终导致的结果就是内存溢出。但是产生内存溢出并不是只有内存泄漏这一种原因 内存泄漏导致溢出的常见场景是大型的 Java后端应用 中在处理用户的请求之后没有及时将用户的数据删除。随着用户请求数量越来越多内存泄漏的对象占满了堆内存最终导致内存溢出。这种产生的内存溢出会直接导致用户请求无法处理影响用户的正常使用。重启可以恢复应用使用但是在运行一段时间之后依然会出现内存溢出第二种常见场景是 分布式任务调度系统如 Elastic-job、Quartz 等进行任务调度时被调度的 Java应用 在调度任务结束中出现了内存泄漏最终导致多次调度之后内存溢出。这种产生的内存溢出会导致应用执行下次的调度任务执行**。同样重启可以恢复应用使用但是在调度执行一段时间之后依然会出现内存溢出。**
解决内存溢出的方法 发现问题 Top 命令
top命令 是 linux 下用来查看系统信息的一个命令它提供给我们去实时地去查看系统的资源比如执行时的进程、线程和系统参数等信息。进程使用的内存为 RES常驻内存 SHR(共享内存) 发现问题 - VisualVM
VisualVM是多功能合一的 Java故障排除工具 并且他是一款 可视化工具整合了 命令行JDK工具 和 轻量级分析功能功能非常强大。这款软件在 Oracle JDK 6~8 中发布但是在 Oracle JDK 9 之后不在JDk安装目录下需要单独下载。下载地址https://visualvm.github.io/
云服务器配置 只能用于测试环境因为会有 STW 影响用户体验 发现问题- Arthas
Arthas 是一款线上监控诊断产品通过全局视角实时查看 应用load、内存、gc、线程 的状态信息**并能在不修改应用代码的情况下对业务问题进行诊断**包括查看方法调用的出入参、异常监测方法执行耗时类加载信息等大大提升线上问题排查效率。 发现问题 - Prometheus Grafana
Prometheus Grafana 是企业中运维常用的监控方案其中 Prometheus 用来采集系统或者应用的相关数据同时具备告警功能。Grafana 可以将 Prometheus 采集到的数据以可视化的方式进行展示。Java程序员 要学会如何读懂 Grafana 展示的 Java虚拟机 相关的参数。 发现问题 - 堆内存状况的对比 产生内存溢出原因一代码中的内存泄漏(压力测试) equals() 和 hashcode() 导致的内存泄漏
1、以 JDK8 为例首先调用 hash方法 计算 key 的哈希值hash方法 中会使用到 key的 hashcode方法。根据 hash方法 的结果决定存放的数组中位置。 2、如果没有元素直接放入。如果有元素先 判断key 是否相等会用到 equals方法如果 key相等直接替换valuekey不相等走链表或者红黑树查找逻辑其中也会使用equals比对是否相同。
1、hashCode 方法实现不正确会导致相同 id的学生对象计算出来的 hash值 不同可能会被分到不同的槽中。 2、equals 方法实现不正确会 导致key在 比对时即便学生对象的 id是相同的也被认为是 不同的key。 3、长时间运行之后 HashMap中会 保存大量相同id的学生 数据。 解决方案
1、在定义新实体时始终重写 equals() 和 hashCode() 方法。 2、重写时一定要确定使用了唯一标识去区分不同的对象比如用户的id等。 3、hashmap 使用时尽量使用编号 id 等数据作为 key不要将整个实体类对象作为 key存放。
案例2内部类引用外部类
1、非静态的内部类默认会持有外部类尽管代码上不再使用外部类所以如果有地方引用了这个非静态内部类会导致外部类也被引用垃圾回收时无法回收这个外部类。2、匿名内部类对象如果在非静态方法中被创建会持有调用者对象垃圾回收时无法回收调用者。
public class Outer {private byte[] bytes new byte[1024 * 1024]; // 外部类持有数据private String name 测试;class Inner { // 改为静态内部类就好了 static class Innerprivate String name;public Inner() {this.name Outer.this.name;}}public static void main(String[] args) throws IOException, InterruptedException {System.in.read();int count 0;ArrayListInner inners new ArrayList();while (true) {if (count % 100 0) {Thread.sleep(10);}inners.add(new Outer().new Inner());}}
}1、这个案例中使用内部类的原因是可以直接获取到外部类中的成员变量值简化开发。如果不想持有外部类对象应该使用静态内部类。 2、使用静态方法可以避免匿名内部类持有调用者对象。
案例3ThreadLocal 的使用 import java.util.concurrent.*;public class Demo5 {public static ThreadLocalObject threadLocal new ThreadLocal():public static void main(String[] args) {ThreadPoolExecutor threadPoolExecutor new ThreadPoolExecutor(Integer.MAX_VALUE, Integer.MAX_VALUE,keepAliveTime:0,TimeUnit.DAYS, new SynchronousQueue());int count 0;while (true) {System.out.println(count);threadPlloExecutor.execute(() - {threadPoolExecutor.set(new byte[1024 * 1024]);// threadLocal.remove(); 线程池一定要释放 threadPoolExecutor });}}
}案例4String 的 intern 方法 import java.util.ArrayList;
import java.util.List;public class Demo6_2 {public static void main(String[] args) {ListString list new ArrayListString();int i 0;while (true) {// String.valueOf(i).intern(); // JDK1.6 perm gen 不会溢出list.add(String.valueOf(i).intern()); // 溢出}}
}案例5通过静态字段保存对象 import java.time.Duration;public class CaffineDemo {public static void main(String[] args) throws InterruptedException {CacheObject, Object build Caffeine.newBuilder().expireAfterWrite(Duration.ofMillis(100)).build();int count 0;while (true) {build.put(count, new byte[1024 * 1024 * 10]);Thread.sleep(100L);}}
}产生内存溢出原因二并发请求问题 并发请求问题指的是用户通过发送请求 向 Java应用 获取数据正常情况下 Java应用将数据返回之后这部分数据就可以在内存中被释放掉。 并发请求问题指的是用户通过发送请求向 Java应用获取数据正常情况下 Java应用 将数据返回之后这部分数据就可以在内存中被释放掉。**但是由于用户的并发请求量有可能很大同时处理数据的时间很长导致大量的数据存在于内存中最终超过了内存的上限导致内存溢出。**这类问题的处理思路和内存泄漏类似首先要定位到对象产生的根源。 使用 Jmeter 进行并发测试发现内存溢出问题 诊断内存快照 当堆内存溢出时需要在堆内存溢出时将整个堆内存保存下来生成内存快照(HeapProfile)文件 使用 MAT打开 hprof文件并选择内存泄漏检测功能MAT 会自行根据内存快照中保存的数据分析内存泄源的根源。 生成内存快照的 Java虚拟机 参数 -XX:HeapDumpOnOutOfMemoryError发生 OutOfMemoryError 错误时自动生成 hprof 内存快照文件。 -XX:HeapDumpPath 指定 hprof文件 的输出路径。
MAT 内存泄漏检测的原理支配树
MAT 提供了称为 **支配树DominatorTree**的对象图。支配树展示的是对象实例间的支配关系。在对象引用图中所有指向对象B的路径都经过对象A则认为 对象A 支配 对象B。 MAT 内存泄漏检测的原理深堆和浅堆 // -XX:HeapDumpBeforeFullGC -XX:HeapDumpPathD:/jvm/heapdemo.hprof
public class HeapDemo {public static void main(String[] args) {TestClass a1 new TestClass();TestClass a2 new TestClass();TestClass a3 new TestClass();String s1 itheima1;String s2 itheima2;String s3 itheima3;a1.list.add(s1);a2.list.add(s1);a2.list.add(s2);a3.list.add(s3);// System.out.print(ClassLayout.parseClass(TestClass.class).toPrintable());s1 null;s2 null;s3 null;System.gc();}
}MAT 内存泄漏检测的原理 导出运行中系统的内存快照并进行分析 分析超大堆的内存快照
在程序员开发用的机器内存范围之内的快照文件直接使用 MAT 打开分析即可。但是经常会遇到服务器上的程序占用的内存达到 10G以上开发机无法正常打开此类内存快照此时需要下载服务器操作系统对应的 MAT。 下载地址: https://eclipse.dev/mat/downloads.php 案例实战 案例1分页查询文章接口的内存溢出 案例2 Mybatis 导致的内存溢出 案例3 导出大文件内存溢出 案例4- ThreadLocal 使用时占用大量内存 案例5文章内容审核接口的内存问题 存在问题
1、线程池参数设置不当会导致大量线程的创建或者队列中保存大量的数据。 2、任务没有持久化一旦走线程池的拒绝策略或者服务宕机、服务器掉电等情况很有可能会丢失任务。 诊断和解决问题 两种方案 在线定位问题 -步骤 1 在线定位问题 btrace 官网https://github.com/btraceio/btrace/releases/latest 2、内存溢出有哪几种产生的原因?
1、持续的内存泄漏内存泄漏持续发生不可被回收同时不再使用的内存越来越多就像滚雪球雪球越滚越大最终内存被消耗完无法分配更多的内存取使用导致内存溢出。 2、并发请求问题用户通过发送请求向Java应用获取数据正常情况下Java应用将数据返回之后这部分数据就可以在内存中被释放掉。但是由于用户的并发请求量有可能很大同时处理数据的时间很长导致大量的数据存在于内存中最终超过了内存的上限导致内存溢出。
3、解决内存泄漏问题的方法是什么
1、发现问题通过监控工具尽可能尽早地发现内存慢慢变大的现象。 2、诊断原因通过分析内存快照或者在线分析方法调用过程诊断问题产生的根源定位到出现问题的源代码。 3、修复源代码中的问题如代码bug、技术方案不合理、业务设计不合理等等。 4、在测试环境验证问题是否已经解决最后发布上线。
GC 调优 GC调优 指的是对**垃圾回收Garbage Collection**进行调优。GC调优的主要目标是避免由垃圾回收引起程序性能下降。 GC调优的核心分成三部分 1、通用 Jvm参数 的设置。 2、特定垃圾回收器的 Jvm参数的设置。 3、解决由频繁的 FULL GC 引起的程序性能问题。
GC调优没有没有唯一的标准答案如何调优与硬件、程序本身、使用情况均有关系重点学习调优的工具和方法。
GC调优的核心指标
所以判断 GC 是否需要调优需要从三方面来考虑与 GC算法 的评判标准类似 1.吞吐量Throughput吞吐量分为业务吞吐量和垃圾回收吞吐量 业务吞吐量 指的在一段时间内程序需要完成的业务数量。比如企业中对于吞吐量的要求可能会是这样的
支持用户每天生成10000笔订单在晚上8点到10点支持用户查询50000条商品信息
GC调优 的方法
保证高吞吐量的常规手段有两条
1、优化业务执行性能减少单次业务的执行时间 2、优化垃圾回收吞吐量 3.内存使用量 内存使用量指的是 Java应用 占用系统内存的最大值一般通过 Jvm参数调整在满足上述两个指标的前提下这个值越小越好。 发现问题页 jstat 工具
Jstat工具 是 JDK 自带的一款监控工具可以提供各种垃圾回收、类加载、编译信息等不同的数据。使用方法为jstat-gc 进程ID 每次统计的间隔 (毫秒) 统计次数 发现问题 visualvm插 件
VisualVm 中提供了一款 visualTool 插件实时监控 Java进程 的堆内存结构,堆内存变化趋势以及垃圾回收时间的变化趋势。同时还可以监控对象晋升的直方图。 Prometheus Grafana
Prometheus Grafana 是企业中运维常用的监控方案其中 Prometheus用来采集系统或者应用的相关数据同时具备告警功能。Grafana 可以将 Prometheus 采集到的数据以可视化的方式进行展示。Java程序员要学会如何读懂 Grafana展示 的 Java虚拟机 相关的参数。 发现问题 -GC 日志
通过 GC日志可以更好的看到垃圾回收细节上的数据同时也可以根据每款垃圾回收器的不同特点更好地发现存在的问题。使用方法JDK 8及以下-XX:PrintGCDetails -Xloggc:文件名使用方法JDK 9-Xlog:gc*:file文件名 发现问题 - GC Viewer GC Viewer 是一个将 GC日志 转换成可视化图表的小工具 github 地址: https://github.com/chewiebug/GcViewer 使用方法java-jar gcviewer_1.3.4.jar 日志文件.log 发现问题 - GCeasy GCeaSy是业界首款使用 AI机器学习技术 在线进行 GC分析 和 诊断的工具。定位内存泄漏、GC延迟高 的问题提供 JVM参数优化建议支持在线的可视化工具图表展示。 官方网站https://gceasy.io/ 发现问题 - 常见的 GC模式
一、正常情况
特点呈现锯齿状对象创建之后内存上升一旦发生垃圾回收之后下降到底部并且每次下降之后的内存大小接近存留的对象较少。 二、缓存对象过多
特点呈现锯齿状对象创建之后内存上升一旦发生垃圾回收之后下降到底部并且每次下降之后的内存大小接近处于比较高的位置。 问题产生原因程序中保存了大量的缓存对象导致 GC 之后无法释放可以使用 MAT 或者 HeapHero等工具 进行分析内存占用的原因。 三、内存泄漏
特点呈现锯齿状每次垃圾回收之后下降到的内存位置越来越高最后由于垃圾回收无法释放空间导致对象无法分配产生 outOfMemory 的错误。 问题产生原因程序中保存了大量的内存泄漏对象导致 GC 之后无法释放可以使用 MAT 或者 HeapHero等工具 进行分析是哪些对象产生了内存泄漏。 四、持续的 Fu GC
特点在某个时间点产生多次 FULL GCCPU使用率 同时飙高用户请求基本无法处理。一段时间之后恢复正常。问题产生原因在该时间范围请求量激增程序开始生成更多对象同时 垃圾收集 无法跟上对象创建速率导致持续地在进行 FULL GC。GC分析报告 五、元空间不足导致的 FULL GC
特点堆内存的大小并不是特别大但是持续发生 FULL GC。问题产生原因元空间大小不足导致持续 FULL GC 回收元空间的数据。GC分析报告 解决 GC 问题的手段 解决GC问题的手段中前三种是比较推荐的手段第四种仅在前三种无法解决时选用 解决问题 优化基础 JVM参数
参数1-Xmx 和-Xms
-Xmx 参数设置的是**最大堆内存**但是由于程序是运行在服务器或者容器上计算可用内存时要将元空间、操作系统、其它软件占用的内存排除掉。
案例服务器内存 4G操作系统元空间最大值其它软件占用 1.5G-Xmx可以设置为 2g。最合理的设置方式应该是根据最大并发量估算服务器的配置然后再根据服务器配置计算最大堆内存的值。 参数1-Xmx 和-Xms -Xms用来设置初始堆大小建议将-Xms设置的和-Xmx一样大有以下几点好处 运行时性能更好堆的扩容是需要向操作系统申请内存的这样会导致程序性能短期下降。可用性问题如果在扩容时其他程序正在使用大量内存很容易因为操作系统内存不足分配失败。启动速度更快Oracle官方文档的原话如果初始堆太小Java应用程序启动会变得很慢因为 JVM 被迫频繁执行垃圾收集直到堆增长到更合理的大小。为了获得最佳启动性能请将初始堆大小设置为与最大堆大小相同。 参数2 -XX:MaxMetaspaceSize 和 -XX:MetaspaceSize -XX:MaxMetaspaceSize值 参数指的是最大元空间大小默认值比较大如果出现元空间内存泄漏会让操作系统可用内存不可控建议根据测试情况设置最大值一般设置为 256m。-XX:MetaspaceSize值 参数指的是到达这个值之后会触发FULL GC网上很多文章的初始元空间大小是错误的后续什么时候再触发 JVM 会自行计算。如果设置为和 MaxMetaspaceSize 一样大就不会 FULL GC但是对象也无法回收。 参数3-Xss虚拟机栈大小
如果我们不指定栈的大小JVM 将创建一个具有默认大小的栈。大小取决于操作系统和计算机的体系结构。 比如 Linu×x86 64位1MB如果不需要用到这么大的栈内存完全可以将此值调小节省内存空间合理值为256k 1m之间。 使用-Xss 256k
参数4不建议手动设置的参数
由 于JVM底层 设计极为复杂一个参数的调整也许让某个接口得益但同样有可能影响其他更多接口。 -Xmn 年轻代的大小默认值为整个堆的 1/3可以根据峰值流量计算最大的年轻代大小尽量让对象只存放在年轻代不进入老年代。但是实际的场景中接口的响应时间、创建对象的大小、程序内部还会有一些定时任务等不确定因素都会导致这个值的大小并不能仅凭计算得出如果设置该值要进行大量的测试。G1垃圾回收器尽量不要设置该值G1会动态调整年轻代的大小。 -XX:SurvivorRatio 伊甸园区和幸存者区的大小比例默认值为8。 -XX:MaxTenuringThreshold 最大晋升阈值年龄大于此值之后会进入老年代。另外 JVM 有动态年龄判断机制将年龄从小到大的对象占据的空间加起来如果大于 survivor 区域的 50%然后把等于或大于该年龄的对象放入到老年代。 -XX:DisableExplicitGC
禁止在代码中使用system·gc(), System·gc() 可能会引起FULL GC在代码中尽量不要使用。使用 DisableExplicitGC参数 可以禁止使用 system.gc() 方法调用。
-XX:HeapDumpOnOutOfMemoryError发生 outofMemoryError错误 时自动生成 hprof内存快照文件。 -XX:HeapDumpPath 指定hprof文件的输出路径。
打印 GC 日志
JDK8及之前-XX:PrintGCDetails -XX:PrintGCDateStamps-Xloggc:文件路径 JDK9及之后-Xlog:gc*:file文件路径 解决问题优化垃圾回收器的参数 这部分优化效果未必出色仅当前边的一些手动无效时才考虑 一个优化的案例
CMS的 并发模式失败concurrentmodefailure现象。由于 CMS 的垃圾清理线程和用户线程是 并行进行的如果在并发清理的过程中老年代的空间不足以容纳放入老年代的对象会产生并发模式失败。
并发模式失败会导致 Java虚拟机 使用 Serial old单线程 进行 FULL GC 回收老年代出现长时间的停顿。 RequestMapping(/fullgc)public class Demo2Controller {private Cache chche Caffeine.newBuilder().weakKeys().softValues().build();private ListObject objs nwe ArrayList();private static final int _1MB 1024 * 1024;// FULLGC 测试// -Xms8g -Xmx8g -Xss256k -XX:MaxMetaspaceSize512m -XX:DisableExplicitGC -XX:HeapDumpOnOutOfMemoryError -XX:HeapDumpPathD:/test.hprof -verbose:gc -XXPrintGCDetails -XX:PrintGCTimeStamps// ps po 50并发 260ms 100并发 474 200并发930// cms -XX:UseParNewGC -XX:UseConcMarkSweepGC 50并发 157ms 200并发 833// g1 JDK11 并发200 248GetMappin(/1)public void test() throws InterruptedException {cache.put(RandomStringUtils.randomAlphabetic(8), new byte[10 * _1MB]);}
}解决方案
减少对象的产生以及对象的晋升。增加堆内存大小优化垃圾回收器的参数比如 -XX:CMSInitiatingOccupancyFraction值当老年代大小到达该阈值时会自动进行 CMS垃圾回收通过控制这个参数提前进行老年代的垃圾回收减少其大小。JDK8中 默认这个参数值为 1根据其他几个参数计算出阈值 ((100 MinHeapFreeRatio) (double)(CMSTriggerRatio * MinHeapFreeRatio) / 100.0)该参数设置完是不会生效的必须开启-XX:UseCMSInitiatingOccupancyOnly参数。 案例实战 性能调优
应用程序在运行过程中经常会出现性能问题比较常见的性能问题现象是
通过 top命令 查看 CPU占用率高接近100甚至 多核CPU 下超过100 都是有可能的。请求单个服务处理时间特别长多服务使用 skywalking 等监控系统来判断是哪一个环节性能低下。程序启动之后运行正常但是在运行一段时间之后无法处理任何的请求**内存和GC正常**
线程转储Thread Dump提供了对所有运行中的线程当前状态的快照。线程转储可以通过 jstack、visualvm 等工具获取。其中包含了线程名、优先级、线程ID、线程状态、线程栈信息等等内容可以用来解决CPU占用率高、死锁等问题。 线程转储者Thread Dump中的几个核心内容
**名称**线程名称通过给线程设置合适的名称更容易“见名知意” 优先级prio): 线程的优先级 JavaIDtid: JVM 中线程的 唯一ID 本地IDnid: 操作系统 分配给线程的 唯一ID **状态**线程的状态分为 NEW 新创建的线程尚未开始执行 RUNNABLE -正在运行或准备执行 BLOCKED - 等待获取监视器锁以进入或重新进入同步块/方法 WAITING 等待其他线程执行特定操作没有时间限制 TIMED_WAITING 等待其他线程在指定时间内执行特定操作 TERMINATED 已完成执行 栈追踪显示整个方法的栈帧信息 线程转储的可视化在线分析平台 1.https://jstack.review/ 2.https://fastthread.io/
案例1CPU 占用率高问题的解决方案 案例2接口响应时间很长的问题 Arthas 的 trace命令
使用 arthas 的 trace命令可以展示出整个方法的调用路径以及每一个方法的执行耗时。 命令trace 类名方法名
添加–skipJDKMethod false 参数可以输出 JDk核心 包中的方法及耗时。添加‘#cost 〉毫秒值’参数只会显示耗时超过该毫秒值的调用。添加 -n 数值参数最多显示该数值条数的数据。所有监控都结束之后输入 stop 结束监控重置 arthas增强的对象。 总结
1、通过 arthas的 trace命令首先找到性能较差的具体方法如果访问量比较大建议设置最小的耗时精确的找到耗时比较高的调用。 2、通过 watch命令查看此调用的参数和返回值重点是参数这样就可以在开发环境或者测试环境模拟类似的现象通过 debug 找到具体的问题根源。 3、使用 stop命令 将所有增强的对象恢复。
案例3:定位偏底层的性能问题 Arthas 的 profile 命令
使用 arthas 的 profile 命令生成性能监控的火焰图。 命令1: profiler start 开始监控方法执行性能 命令2: profiler stop – format html 以 HTML 的方式生成火焰图 火焰图中一般找绿色部分Java中栈顶上比较平的部分很可能就是性能的瓶颈。 性能调优解决的问题
应用程序在运行过程中经常会出现性能问题比较常见的性能问题现象是
1、通过 top命令 查看 CPU占用率高接近 100甚至 多核CPU下 超过 100都是 有可能的。 2、请求单个服务处理时间特别长多服务使用 skywalking等监控系统 来判断是哪一个环节性能低下。 3、程序启动之后运行正常但是在运行一段时间之后无法处理任何的请求内存和GC正常。
案例4线程被耗尽问题 解决方案
3、使用 fastthread 自动检测线程问题。https://fastthread.io/ Fastthread 和 Gceasy类似是一款在线的Al自动线程问题检测工具可以提供线程分析报告。通过报告查看是否存在死锁问题。 性能调优的方法 JIT 对程序性能的影响
Java 程序在运行过程中JIT 即时编译器会实时对代码进行性能优化所以仅凭少量的测试是无法真实反应运行系统最终给用户提供的性能。如下图随着执行次数的增加程序性能会逐渐优化。 OpenJDK 中提供了一款叫 JMHJava Microbenchmark Harness的工具可以准确地对 Java代码 进行基准测试量化方法的执行性能。 官网地址https://github.com/openjdk/jmh JMH 会首先执行预热过程确保 JIT对代码进行优化之后再进行真正的迭代测试最后输出测试的结果。 import java.util.concurrent.TimeUnit;
import org.openjdk.jmh.annotations.*;// 预热次数 时间
Warmup(iterations 5, time 1)
// 启动多少个线程
Fork(value1, jvmArgsAppend {-Xms1g, -Xmx1g})
// 指定显示结果
BenchamarkMode(Mode.AverageTime)
// 指定显示结果单位
OutputTimeUnit(TimeUnit.NANOSECONDS)
// 变量共享范围
State(Scope.Benchmark)
public class MyBenchmark {Benchmarkpublic void testMethod() {// place your benchmarked code hereint i 0;i;return i;}// 在项目中测试时尽量打包成 jar 包public static void main(String[] args) throws RunnerException {Options options new OptionsBuilder();.include(MyBenchmark.class.getSimpleName()).forks(1).build();new Runner(options).run();}
}编写测试方法几个需要注意的点 死代码问题 黑洞的用法 通过 maven 的 verify命令检测代码问题并打包成 jar包。通过 java -jar target/benchmarks.jar 命令执行基准测试。 测试结果通过 https://imh.morethan.io/ 生成可视化的结果。
案例日期格式化方法性能测试 总结日期格式化方法性能测试 案例实战