代码之家  ›  专栏  ›  技术社区  ›  Arkaitz Jimenez

Java protobuf创建太多对象

  •  0
  • Arkaitz Jimenez  · 技术社区  · 7 年前

    我有一个jetty服务器在后端和转换protobufs frontend.proto->backend.proto和backend.proto->frontend.proto之间进行代理。


    但是,当负载达到峰值时,第99个增加+10,而第99.9个增加+60。

    我已经调查过了,延迟请求是由于GC疏散暂停引起的,我确信,这种暂停需要50-70ms,在山谷负载下每15秒运行一次,但在峰值负载下每3-5秒跳一次,持续时间相同。
    当GC频率低于8-9秒时,99.9%的数据就会迅速上升,我可以同时看到慢速请求的调试日志和GC日志。

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

    • Eden空间填满并触发GC暂停
    • 所以大部分的物品在伊甸园已经过期了
    • 这是有意义的,因为请求需要30-40毫秒,而且大多数对象的生存期都与请求的生存期相关联

    我试过玩GCPauseMillis和Eden大小的游戏,但似乎没有什么不同,它从不少于50ms,而更大的Eden意味着频率更低,但停顿时间更长

    我在这里看到两个选项:

    1. 在java protobuf中以某种方式重用对象创建:似乎是不可能的,阅读了大量的文章和邮件,并没有这样设置,他们只是说“java对象分配非常有效,它应该能够处理正在创建的许多对象”,虽然这是真的,但是相关的GC开销正在扼杀我的99.9
    2. 让GC更频繁地运行,比如每秒运行一次,以减少收集时间,这样它将停止更多的请求,但会缩短时间:我一直在使用gcmaxmlis和Eden大小,但似乎无法将其降低

    我把gc日志上传到 gc_log

    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 回复  |  直到 7 年前