开发者社区> 问答> 正文

RocketMQ Intrinsic会导致应用卡顿吗?

RocketMQ Intrinsic会导致应用卡顿吗?

展开
收起
1358896759097293 2021-05-04 15:27:26 860 0
1 条回答
写回答
取消 提交回答
  • 45271990@qq.com

    RocketMQ 是阿里巴巴开源的MQ产品,使用非常广泛,里面有个函数叫“warmMappedFile”,指的是RocketMQ是通过warmMapped机制内存映射磁盘去做IO,在申请完一块磁盘映射的内存以后,会去做预热。 这里有for循环“for (int i = 0, j = 0; i < this.fileSize”,每隔一个PACG_SIZE去“byteBuffer.put(i, (byte) 0)”;,这样的话,操作系统就会发生缺页,把内存真正分配出来,而不只是EMV数据结构。分配出来以后,等到程序真正使用这块内存的时候,就是纯内存IO,不太会触发这种缺页了,可以变得更快,目的是减少程序卡顿。 34.png

    但是后面加了if这一段,可以想到刚开始这个循环有问题,因为 byteBuffer.put是Intrinsic,最底层是Intrinsic,方法返回的时候,没有方法调用。JVM在方法返回以及循环末尾检查,是否有Safepoints,来看是否要进入GC,但是因为这是一个Intrinsic,所以没有到检查点,同样这是一个CountedLoop,也没法去进入检查点。因为JVM有个机制,如果这是一个 int作为index去Counted次数的话,为了性能是不会去检查,因为它认为这是有限次的循环,所以不用检查次数。 这种机制循环里面非常简单,中间有可能因为操作系统原因带来卡顿,导致循环,基本上没法进入GC,因为线程没有进入Safepoints,整个界面都没法进入GC, 夯住很长时间,当时大家觉得很不可思议,但是通过一个很简单方法修好了,就是每隔1000字循环的时候,去调一个“Thread.sleep(0)”。 刚刚提到,“byteBuffer.put”没法出发,Thread.sleep是个JNI,返回的时候会检查Safepoints,所以就可以让这个程序能够进入到Safepoints,这个代码就不会影响JVM进入到GC了,代码目前还可以从开源软件上看到。

    “-XX:+UseCountedLoopSafepoints”
    
    

    解决这个问题,还有另一种方式,通过一个选项叫“-XX:+UseCountedLoopSafepoints”,可以JVM自动在CountedLoop结尾检查这Safepoints,当然这带来的副作用是,CountedLoop末尾都会检查Safepoints,这样就会影响整体性能。

    2021-05-05 22:54:00
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
RocketMQ Client-GO 介绍 立即下载
RocketMQ Prometheus Exporter 打造定制化 DevOps 平台 立即下载
基于 RocketMQ Prometheus Exporter 打造定制化 DevOps 平台 立即下载