Java protobuf创建太多对象

时间:2019-03-07 08:58:17

标签: java garbage-collection protocol-buffers

我有一个码头服务器代理,可以在后端之间转换protobufs frontend.proto-> backend.proto和backend.proto-> frontend.proto。

在负载未达到峰值的情况下,请求占用的时间低于20ms(第99位)和40ms(99.9)以下。
但是,当负载达到峰值时,第99个增加+10,而第99.9个增加+60。

我已经调查过,延迟的请求是由GC疏散暂停引起的,我敢肯定,此暂停需要50-70ms的时间,在谷底负载下每15秒运行一次,但在3-5秒内跳升一次峰值负载,持续时间是相同的。
一旦GC频率低于8-9秒,第99.9个百分点就会上升,我可以同时看到慢速请求的调试日志和GC日志。

我已经使用JProfiler,Yourkit和VisualVM进行了分析,并发现:

  • 伊甸空间填满并触发GC暂停
  • 很少有对象移动到Survivor中(12G中只有几MB)
  • 因此大多数对象在伊甸园中已经过期
  • 这很有意义,因为请求需要30到40毫秒,并且大多数对象的生命周期都与请求生命周期相关联
  • 大多数对象是在protobuf反序列化期间创建的

我尝试过使用GCPauseMillis和Eden大小,但是似乎没有什么区别,它不会少于50毫秒,而更大的Eden则意味着更少的频率但更长的暂停时间

我在这里看到2个选项:

  1. 以某种方式重用java-protobuf中的对象创建:似乎是不可能的,通读了大量的帖子和邮件,并且没有这样设置,他们只是说“ Java对象分配非常有效,它应该能够处理许多对象被创建”,而确实如此,相关的GC成本使我的第99.9位
  2. 丧命
  3. 使GC的运行频率更高,例如每秒一次,以缩短收集时间,以便停止更多请求,但时间更短:我一直在使用GCMaxMillis和Eden尺寸,但似乎无法理解低于

我将gc日志上传到了gc_log

Java版本:

java version "1.8.0_131"
Java(TM) SE Runtime Environment (build 1.8.0_131-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.131-b11, mixed mode)

GC详细信息:

-XX:CICompilerCount=12 -XX:ConcGCThreads=5 -XX:ErrorFile=/home/y/var/crash/hs_err_pid%p.log -XX:+FlightRecorder -XX:G1HeapRegionSize=4194304 -XX:GCLogFileSize=4194304 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/home/y/logs/yjava_jetty -XX:InitialHeapSize=12884901888 -XX:MarkStackSize=4194304 -XX:MaxHeapSize=12884901888 -XX:MaxNewSize=7730102272 -XX:MinHeapDeltaBytes=4194304 -XX:NumberOfGCLogFiles=10 -XX:+ParallelRefProcEnabled -XX:+PrintGC -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+UnlockCommercialFeatures -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseFastUnorderedTimeStamps -XX:+UseG1GC -XX:+UseGCLogFileRotation

0 个答案:

没有答案