JVM деоптимизация принимает процессор, когда Joda-время достигает високосного дня - PullRequest
6 голосов
/ 05 марта 2020

После 28.02.2020 мы обнаружили, что наши кластеры Elasticsearch, используемые для обработки журналов (с полями даты), не выполнялись.

Это 64-битный сервер HotSpot (TM), виртуальная машина 18.9 (сборка 11.0.3 + 12-LTS), которую мы использовали для запуска кластеров Elasticsearch.

Журнал деоптимизации jstack & JVM привел нас для деоптимизации (причина = unstable_if) проверки високосного года во время joda:

stacktrace

jstack показывает работоспособные [объемные] потоки эластичного поиска, но на самом деле они заблокированы (согласно gstack) из-за JVM деоптимизация в BasicGJChronology. java: 185 и BasicGJChronology. java: 187。 Обе две строки являются проверкой високосного года.

jstack:

"elasticsearch[xxx][bulk][T#19]" #312 daemon prio=5 os_prio=0 cpu=1972224606.34ms elapsed=12348671.96s tid=0x00007f90a0006800 nid=0xdd41 runnable  [0x00007f8f170ee000]
   java.lang.Thread.State: RUNNABLE
    at org.joda.time.chrono.BasicGJChronology.setYear(BasicGJChronology.java:185)
    at org.joda.time.chrono.BasicYearDateTimeField.setExtended(BasicYearDateTimeField.java:92)
    at org.joda.time.format.DateTimeParserBucket$SavedField.set(DateTimeParserBucket.java:568)
    at org.joda.time.format.DateTimeParserBucket.computeMillis(DateTimeParserBucket.java:451)
    at org.joda.time.format.DateTimeParserBucket.doParseMillis(DateTimeParserBucket.java:182)
    at org.joda.time.format.DateTimeFormatter.parseMillis(DateTimeFormatter.java:826)
    at org.elasticsearch.index.mapper.DateFieldMapper$DateFieldType.parse(DateFieldMapper.java:248)
    at org.elasticsearch.index.mapper.DateFieldMapper.parseCreateField(DateFieldMapper.java:456)
    at org.elasticsearch.index.mapper.FieldMapper.parse(FieldMapper.java:297)
--
"elasticsearch[xxx][bulk][T#20]" #315 daemon prio=5 os_prio=0 cpu=1975796442.21ms elapsed=12348662.71s tid=0x00007f92f4048000 nid=0xdd83 runnable  [0x00007f8f16cea000]
   java.lang.Thread.State: RUNNABLE
    at org.joda.time.chrono.BasicGJChronology.setYear(BasicGJChronology.java:187)
    at org.joda.time.chrono.BasicYearDateTimeField.setExtended(BasicYearDateTimeField.java:92)
    at org.joda.time.format.DateTimeParserBucket$SavedField.set(DateTimeParserBucket.java:568)
    at org.joda.time.format.DateTimeParserBucket.computeMillis(DateTimeParserBucket.java:451)
    at org.joda.time.format.DateTimeParserBucket.doParseMillis(DateTimeParserBucket.java:182)
    at org.joda.time.format.DateTimeFormatter.parseMillis(DateTimeFormatter.java:826)
    at org.elasticsearch.index.mapper.DateFieldMapper$DateFieldType.parse(DateFieldMapper.java:248)
    at org.elasticsearch.index.mapper.DateFieldMapper.parseCreateField(DateFieldMapper.java:456)
at org.elasticsearch.index.mapper.FieldMapper.parse(FieldMapper.java:297)

gstack вышеуказанных объемных потоков :

#0  0x00007f3cf8f566d5 in pthread_cond_wait@@GLIBC_2.3.2 () from /lib64/libpthread.so.0
#1  0x00007f3cf7ef8ef3 in os::PlatformEvent::park() () from /usr/java/jdk-11.0.3/lib/server/libjvm.so
#2  0x00007f3cf7e9feb8 in Monitor::lock_without_safepoint_check() () from /usr/java/jdk-11.0.3/lib/server/libjvm.so
#3  0x00007f3cf79977f3 in Events::log(Thread*, char const*, ...) () from /usr/java/jdk-11.0.3/lib/server/libjvm.so
#4  0x00007f3cf799411a in Deoptimization::uncommon_trap_inner(JavaThread*, int) () from /usr/java/jdk-11.0.3/lib/server/libjvm.so
#5  0x00007f3cf79973d2 in Deoptimization::uncommon_trap(JavaThread*, int, int) () from /usr/java/jdk-11.0.3/lib/server/libjvm.so

фрагменты кода от BasicGJChronology. java:

    long setYear(long instant, int year) {
        int thisYear = getYear(instant);
        int dayOfYear = getDayOfYear(instant, thisYear);
        int millisOfDay = getMillisOfDay(instant);

        if (dayOfYear > (31 + 28)) { // after Feb 28
            if (isLeapYear(thisYear)) { // LINE 185
                // Current date is Feb 29 or later.
                if (!isLeapYear(year)) { // LINE 187
                    // Moving to a non-leap year, Feb 29 does not exist.
                    dayOfYear--;
                }
            } else {
                // Current date is Mar 01 or later.
                if (isLeapYear(year)) {
                    // Moving to a leap year, account for Feb 29.
                    dayOfYear++;
                }
            }
        }
...

График пламени

От левой вершины на графике вы можете найти деоптимизацию.

enter image description here

журнал деоптимизации в hs_err_pidxxx.log

Deoptimization events (10 events):
Event: 12413938.027 Thread 0x00007f6174013000 Uncommon trap: reason=unstable_if action=none pc=0x00007f65f543ff88 method=org.joda.time.chrono.BasicGJChronology.setYear(JI)J @ 36 c2
Event: 12413938.027 Thread 0x00007f6174013000 Uncommon trap: reason=unstable_if action=none pc=0x00007f65f543ff88 method=org.joda.time.chrono.BasicGJChronology.setYear(JI)J @ 36 c2

вопросы

  1. Как мы можем смягчить влияние деоптимизации на производительность? Кажется, это больше всего влияет не на стоимость JIT-компиляции, а на pthread_cond_wait ведения журнала?

  2. Кластеры работали более года. Будет ли повторный перезапуск решить unstable_if?

  3. Почему это unstable_if? Извините, я ничего не знаю о тактике производительности HotSpot. Но мое внутреннее чувство заключается в том, что состояние должно быть очень стабильным после високосного дня (все еще нестабильным в 3/5/2020). 31.12.2020 меня тоже волнует, так как я понятия не имею о unstable_if.

1 Ответ

0 голосов
/ 09 марта 2020

Кто-то предложил использовать -XX: PerMethodRecompilationCutoff = 10000 -XX: PerBytecodeRecompilationCutoff = 10000 на другом форуме.

И он подумал, что вместо Action_reinterpret, Action_none (возможно, после некоторой переинтерпретации) является проблемой.

Он также упомянул, что эта ошибка может быть связана, но я не изучал: https://bugs.java.com/bugdatabase/view_bug.do?bug_id=8227523

Извините, я не вставил оригинальный ответ, поскольку его нет на английском языке sh.

...