Подтвердить что ты не робот

Объекты обработки ссылок Java G1 GC работают медленно

У меня работает счетчик на Java. Он работает 24 часа, а хиты проходят примерно 100 раз в секунду. В течение дня время обработки GC медленно увеличивается с 20-60 мс до 10000-60000 мс, а затем падает до 20-60 мс. Такая картина повторяется время от времени. Из журналов GC я обнаружил, что в основном все время GC тратится на обработку ссылочных объектов (Ref Proc). Итак, каковы были причины такого длительного времени GC?

Server: Amazon EC2 m1.small
OS: Ubuntu 10.04.3 LTS
Java: Oracle 1.7.0_07

Пример журналов GC:

2012-09-13T16:51:20.091+0400: 167239.936: [GC pause (young), 62.58395400 secs]
...
[Other: 62489.7 ms]
    [Choose CSet:   0.0 ms]
    [Ref Proc: 62433.9 ms]
    [Ref Enq:   0.0 ms]
    [Free CSet:   0.7 ms]
[Eden: 200M(200M)->0B(199M) Survivors: 4096K->5120K Heap: 578M(1024M)->380M(1024M)]

Время - график "Ref Proc":

09:37:59 - 242.4 ms
09:38:50 - 226.0 ms
09:39:00 - 83.6 ms
...
11:45:22 - 451.8 ms
11:46:04 - 489.3 ms
11:46:46 - 505.6 ms
...
14:05:40 - 1027.3 ms
14:06:01 - 796.6 ms
14:06:35 - 1064.0 ms
...
15:44:32 - 1920.4 ms
15:45:04 - 2116.7 ms
15:45:39 - 2196.8 ms
...
16:19:07 - 3983.3 ms
16:19:43 - 4494.9 ms
16:20:16 - 4065.2 ms
...
16:33:11 - 7690.1 ms
16:33:50 - 8501.4 ms
16:34:28 - 8059.3 ms
...
16:47:14 - 51378.6 ms
16:49:11 - 57529.2 ms
16:51:20 - 62433.9 ms
16:53:00 - 46.1 ms
16:53:30 - 45.5 ms
16:54:03 - 45.0 ms
...
16:54:38 - 57.0 ms
16:55:09 - 20.9 ms
16:55:43 - 21.3 ms
...
16:09:45 - 134.3 ms
16:10:21 - 142.1 ms
16:10:58 - 147.5 ms
...
17:18:51 - 177.3 ms
17:19:27 - 135.8 ms
17:20:03 - 179.6 ms

Я нашел в java-источнике параметр PrintReferenceGC. GC log показал следующий

[SoftReference, 0 refs, 0.0000050 secs]
[WeakReference, 6 refs, 0.0000030 secs]
[FinalReference, 113 refs, 0.0011180 secs]
[PhantomReference, 0 refs, 0.0000020 secs]
[JNI Weak Reference, 3.9010450 secs]

Это некоторая проблема слабого справочника JNI.

4b9b3361

Ответ 1

Важно, чтобы все мои прогоны были с профилировщиком Yourkit. Я установил builddebug build OpenJDK7. На этой версии есть параметр -XX: + TraceReferenceGC. После запуска с этим параметром gc log показал около 5000 некоторых финализаторов. Эта проблема была решена путем отключения сокет-зондов Yourkit.

Ответ 2

В качестве первого шага вы можете использовать VisualVM или любой инструмент для анализа вашего шаблона использования кучи. У вас может быть решение, оптимизируя ваш код, проверяя горячие точки создания объекта, и это должно быть постоянным решением.

Если это невозможно, вам нужно найти оптимальный размер кучи и алгоритм GC, подходящий для поведения ваших приложений. Это будет метод проб и ошибок. Вы обязательно должны пройти настройку doc. Настройка, которую вы сейчас выполняете, может снова стать неэффективной позже при изменении вашего поведения приложения или изменении шаблона загрузки.

Попробуйте найти подходящий сборщик для вас. Вы будете изменять некоторые параметры, такие как

    -XX:+UseConcMarkSweepGC        
    -XX:SurvivorRatio=10 
    -XX:TargetSurvivorRatio=90 
    -XX:MaxTenuringThreshold=30

методом проб и ошибок.