网站首页 > 技术文章 正文
专注于Java领域优质技术,欢迎关注
作者: 占小狼 来自:占小狼的博客
"狼哥,我发现新大陆了,等会发你代码"
"咋了,这么激动"
"等会..."
List<Integer> list0 = new ArrayList<Integer>();
long start0 = System.currentTimeMillis();
for (int i = 0; i < 10000000; i++)
{
list0.add(i);
}
System.out.println(System.currentTimeMillis() - start0);
long start1 = System.currentTimeMillis();
List<Integer> list1 = new ArrayList<Integer>();
for (int i = 10000000; i < 20000000; i++)
{
list1.add(i);
}
System.out.println(System.currentTimeMillis() - start1);
"我在一个ArrayList中连续插入1千万条数据,结果耗时不一样,分别是
2346
797
没搞明白"
我看了一眼,就知道这小伙底盘不稳。
"你加个 -XX:+PrintGCDetails -XX:+PrintGCDateStamps,看下第一次是不是有Full GC"
"明白,我再试试看"
几分钟后...
"狼哥,第一次Full GC果然耗时了1.87s,那我把堆调大看看,避免Full GC"
几分钟后...
"这次没有GC了,但是每次运行,前一个都比后一个耗时多点,这是怎么回事?"
"你试试放在不同线程中运行?"
"好"
又几分钟后...
2019-09-28T09:49:07.519-0800: [GC (Allocation Failure) [PSYoungGen: 54888K->10738K(76288K)] 54888K->36180K(251392K), 0.0520111 secs] [Times: user=0.24 sys=0.03, real=0.06 secs]
2019-09-28T09:49:07.590-0800: [GC (Allocation Failure) [PSYounGen: 74092K->10736K(141824K)] 99534K->80803K(316928K), 0.0693607 secs] [Times: user=0.39 sys=0.03, real=0.06 secs]
2019-09-28T09:49:07.751-0800: [GC (Allocation Failure)[PSYoungGen: 141808K->10736K(141824K)] 211875K->188026K(320512K), 0.1829926 secs] [Times: user=1.02 sys=0.10, real=0.18 secs]
2019-09-28T09:49:07.934-0800: [Full GC (Ergonomics) [PSYoungGen:10736K->0K(141824K)] [ParOldGen: 177290K->171620K(402432K)] 188026K->171620K(544256K), [Metaspace:3062K->3062K(1056768K)], 1.8672996 secs][Times: user=5.96 sys=0.03, real=1.87 secs]
2365
2019-09-28T09:49:09.832-0800: [GC (Allocation Failure) [PSYoungGen: 129254K->10738K(196608K)] 300875K->282609K(599040K), 0.1039307 secs] [Times: user=0.74 sys=0.07, real=0.10 secs]
2019-09-28T09:49:09.936-0800: [Full GC (Ergonomics) [PSYoungGen: 10738K->0K(196608K)] [ParOldGen: 271871K->36047K(372736K)] 282609K->36047K(569344K), [Metaspace: 3067K->3067K(1056768K)], 0.4510440 secs] [Times: user=1.82 sys=0.01, real=0.45 secs]
2019-09-28T09:49:10.440-0800: [GC (Allocation Failure) [PSYoungGen: 185856K->10752K(264704K)] 221903K->171359K(637440K), 0.1292143 secs] [Times: user=0.97 sys=0.01, real=0.12 secs]
"狼哥,第一次Full GC果
"在不同线程中执行,两者耗时几乎一致,这是为什么?"
"你知道OSR吗?"
"不知道."
"那我跟你大概讲讲."
OSR(On-Stack Replacement ),是一种在运行时替换正在运行的函数/方法的栈帧的技术。
在现代的主流JVM中,都具备了多层编译的能力,一开始以解释的方式进行执行,这种性能相对来说(和c++比)会慢一点,但是一旦发现某一个函数执行很频繁的时候,就会采用JIT编译,提高函数执行性能(大部分比c++还快)。
但是,如果以函数为单位进行JIT编译,那么就无法应对main函数中包含循环体的情况,这个时候,OSR就派上了用场。
与其编译整个方法,我们可以在发现某个方法里有循环很热的时候,选择只编译方法里的某个循环,当循环体执行到 i = 5000 的时候,循环计数器达到了触发OSR编译的阈值,等编译完成之后,就可以执行编译后生成的代码。所以在上面例子中,当我们第二次执行循环体的时候,已经在执行OSR编译后的代码,那么在性能上会比前一次会快那么一点点。
OSR更具体的实现原理,本文就不多加深究了,有兴趣的同学可以阅读下R大的知乎。https://tinyurl.com/y3yxu8fc
猜你喜欢
- 2024-09-21 Java并发编程:LongAdder | LongAccumulator 对比测试
- 2024-09-21 「Java技巧」优雅的统计程序的执行时间,别再用System.cur
- 2024-09-21 Flink SQL 知其所以然(九)| SQL 的时间语义
- 2024-09-21 《Java实战之内存模型》详解篇(java内存模型happens before)
- 2024-09-21 比反射更快!使用ASM获取class信息(ClassReader)
- 2024-09-21 了解Java线程优先级,更要知道对应操作系统的优先级,不然会踩坑
- 2024-09-21 让大学生写的一个计算时间的方法,有人看得出来是在做什么吗?这
- 2024-09-21 Java基础——Java多线程(Lock接口详解)
- 2024-09-21 JVM性能调优监控工具jps、jstack、jmap、jhat、jstat使用详解
- 2024-09-21 最近学到的限流知识(限流的含义)
- 1514℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 569℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 510℃MySQL service启动脚本浅析(r12笔记第59天)
- 486℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 485℃启用MySQL查询缓存(mysql8.0查询缓存)
- 467℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 446℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 444℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- c语言min函数头文件 (68)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)