美文网首页城市故事
我将1000万条数据连续插入ArrayList后,竟然发现了JV

我将1000万条数据连续插入ArrayList后,竟然发现了JV

作者: 北熊行 | 来源:发表于2019-11-15 20:15 被阅读0次

    "哥,我发现新大陆了,等会发你代码"

    "咋了,这么激动"

    "等会..."

    "我在一个ArrayList中连续插入1千万条数据,结果耗时不一样,分别是 2346 797 没搞明白 "

    我看了一眼,就知道这小伙底盘不稳。

    "你加个 -XX:+PrintGCDetails -XX:+PrintGCDateStamps,看下第一次是不是有Full GC"

    "明白,我再试试看"

    几分钟后...

    2019-09-28T09:49:07.519-0800: [GC (Allocation Failure) [PSYoungGen:54888K->10738K(76288K)]54888K->36180K(251392K),0.0520111secs] [Times: user=0.24sys=0.03, real=0.06secs]2019-09-28T09:49:07.590-0800: [GC (Allocation Failure) [PSYoungGen:74092K->10736K(141824K)]99534K->80803K(316928K),0.0693607secs] [Times: user=0.39sys=0.03, real=0.06secs]2019-09-28T09:49:07.751-0800: [GC (Allocation Failure) [PSYoungGen:141808K->10736K(141824K)]211875K->188026K(320512K),0.1829926secs] [Times: user=1.02sys=0.10, real=0.18secs]2019-09-28T09:49:07.934-0800: [FullGC (Ergonomics) [PSYoungGen:10736K->0K(141824K)] [ParOldGen:177290K->171620K(402432K)]188026K->171620K(544256K), [Metaspace:3062K->3062K(1056768K)],1.8672996secs] [Times: user=5.96sys=0.03, real=1.87secs]23652019-09-28T09:49:09.832-0800: [GC (Allocation Failure) [PSYoungGen:129254K->10738K(196608K)]300875K->282609K(599040K),0.1039307secs] [Times: user=0.74sys=0.07, real=0.10secs]2019-09-28T09:49:09.936-0800: [FullGC (Ergonomics) [PSYoungGen:10738K->0K(196608K)] [ParOldGen:271871K->36047K(372736K)]282609K->36047K(569344K), [Metaspace:3067K->3067K(1056768K)],0.4510440secs] [Times: user=1.82sys=0.01, real=0.45secs]2019-09-28T09:49:10.440-0800: [GC (Allocation Failure) [PSYoungGen:185856K->10752K(264704K)]221903K->171359K(637440K),0.1292143secs] [Times: user=0.97sys=0.01, real=0.12secs]772

    "狼哥,第一次Full GC果然耗时了1.87s,那我把堆调大看看,避免Full GC"

    几分钟后...

    "这次没有GC了,但是每次运行,前一个都比后一个耗时多点,这是怎么回事?"

    "你试试放在不同线程中运行?"

    "好"

    又几分钟后...

    "在不同线程中执行,两者耗时几乎一致,这是为什么?"

    "你知道OSR吗?"

    "不知道."

    "那我跟你大概讲讲."

    OSR(On-Stack Replacement ),是一种在运行时替换正在运行的函数/方法的栈帧的技术。

    在现代的主流JVM中,都具备了多层编译的能力,一开始以解释的方式进行执行,这种性能相对来说(和c++比)会慢一点,但是一旦发现某一个函数执行很频繁的时候,就会采用JIT编译,提高函数执行性能(大部分比c++还快)。

    但是,如果以函数为单位进行JIT编译,那么就无法应对main函数中包含循环体的情况,这个时候,OSR就派上了用场。

    与其编译整个方法,我们可以在发现某个方法里有循环很热的时候,选择只编译方法里的某个循环,当循环体执行到 i = 5000 的时候,循环计数器达到了触发OSR编译的阈值,等编译完成之后,就可以执行编译后生成的代码。所以在上面例子中,当我们第二次执行循环体的时候,已经在执行OSR编译后的代码,那么在性能上会比前一次会快那么一点点。

    关注我,私信回复“资料”,即可领取更多java架构资料!!

    相关文章

      网友评论

        本文标题:我将1000万条数据连续插入ArrayList后,竟然发现了JV

        本文链接:https://www.haomeiwen.com/subject/ijzsictx.html