Повільний додаток, часті JVM зависають із налаштуваннями одного процесора та Java 12+


23

У нас є клієнтська програма (з 10+ роками розвитку). Нещодавно його JDK було оновлено з OpenJDK 11 до OpenJDK 14. На однопроцесорних процесорах (відключення гіперточок) Windows 10 (і всередині машин VirtualBox із лише одним доступним процесором) програма запускається досить повільно порівняно з Java 11. Крім того, вона використовує 100% процесора більшу частину часу. Ми також могли б відтворити проблему із встановленням спорідненості процесора лише до одного процесора ( c:\windows\system32\cmd.exe /C start /affinity 1 ...).

Деякий вимір із запуском програми та виконанням запиту з мінімальною ручною взаємодією на моїй машині VirtualBox:

  • OpenJDK 11.0.2: 36 секунд
  • OpenJDK 13.0.2: ~ 1,5 хвилини
  • OpenJDK 13.0.2 з -XX:-UseBiasedLocking: 46 секунд
  • OpenJDK 13.0.2 з -XX:-ThreadLocalHandshakes: 40 секунд
  • OpenJDK 14: 5-6 хвилин
  • OpenJDK 14 з -XX:-UseBiasedLocking: 3-3,5 хв
  • OpenJDK 15 EA Build 20: ~ 4,5 хв

Змінено лише використаний JDK (та згадані параметри). (-XX:-ThreadLocalHandshakes недоступно на Java 14.)

Ми спробували записати те, що робить JDK 14 -Xlog:all=debug:file=app.txt:uptime,tid,level,tags:filecount=50.

Підрахунок ліній журналу за кожну секунду здається досить плавним у OpenJDK 11.0.2:

$ cat jdk11-log/app* | grep "^\[" | cut -d. -f 1 | cut -d[ -f 2 | sort | uniq -c | sort -k 2 -n
  30710 0
  44012 1
  55461 2
  55974 3
  27182 4
  41292 5
  43796 6
  51889 7
  54170 8
  58850 9
  51422 10
  44378 11
  41405 12
  53589 13
  41696 14
  29526 15
   2350 16
  50228 17
  62623 18
  42684 19
  45045 20

З іншого боку, OpenJDK 14, здається, має цікаві спокійні періоди:

$ cat jdk14-log/app* | grep "^\[" | cut -d. -f 1 | cut -d[ -f 2 | sort | uniq -c | sort -k 2 -n
   7726 0
   1715 5
  10744 6
   4341 11
  42792 12
  45979 13
  38783 14
  17253 21
  34747 22
   1025 28
   2079 33
   2398 39
   3016 44

Отже, що відбувається між секундами 1-4, 7-10 та 14-20?

...
[0.350s][7248][debug][class,resolve        ] jdk.internal.ref.CleanerFactory$1 java.lang.Thread CleanerFactory.java:45
[0.350s][7248][debug][class,resolve        ] jdk.internal.ref.CleanerImpl java.lang.Thread CleanerImpl.java:117
[0.350s][7248][info ][biasedlocking        ] Aligned thread 0x000000001727e010 to 0x000000001727e800
[0.350s][7248][info ][os,thread            ] Thread started (tid: 2944, attributes: stacksize: default, flags: CREATE_SUSPENDED STACK_SIZE_PARAM_IS)
[0.350s][6884][info ][os,thread            ] Thread is alive (tid: 6884).
[0.350s][6884][debug][os,thread            ] Thread 6884 stack dimensions: 0x00000000175b0000-0x00000000176b0000 (1024k).
[0.350s][6884][debug][os,thread            ] Thread 6884 stack guard pages activated: 0x00000000175b0000-0x00000000175b4000.
[0.350s][7248][debug][thread,smr           ] tid=7248: Threads::add: new ThreadsList=0x0000000017254500
[0.350s][7248][debug][thread,smr           ] tid=7248: ThreadsSMRSupport::free_list: threads=0x0000000017253d50 is freed.
[0.350s][2944][info ][os,thread            ] Thread is alive (tid: 2944).
[0.350s][2944][debug][os,thread            ] Thread 2944 stack dimensions: 0x00000000177b0000-0x00000000178b0000 (1024k).
[0.350s][2944][debug][os,thread            ] Thread 2944 stack guard pages activated: 0x00000000177b0000-0x00000000177b4000.
[0.351s][2944][debug][class,resolve        ] java.lang.Thread java.lang.Runnable Thread.java:832
[0.351s][2944][debug][class,resolve        ] jdk.internal.ref.CleanerImpl jdk.internal.misc.InnocuousThread CleanerImpl.java:135
[0.351s][2944][debug][class,resolve        ] jdk.internal.ref.CleanerImpl jdk.internal.ref.PhantomCleanable CleanerImpl.java:138
[0.351s][2944][info ][biasedlocking,handshake] JavaThread 0x000000001727e800 handshaking JavaThread 0x000000000286d800 to revoke object 0x00000000c0087f78
[0.351s][2944][debug][vmthread               ] Adding VM operation: HandshakeOneThread
[0.351s][6708][debug][vmthread               ] Evaluating non-safepoint VM operation: HandshakeOneThread
[0.351s][6708][debug][vmoperation            ] begin VM_Operation (0x00000000178af250): HandshakeOneThread, mode: no safepoint, requested by thread 0x000000001727e800

# no log until 5.723s

[5.723s][7248][info ][biasedlocking          ]   Revoked bias of currently-unlocked object
[5.723s][7248][debug][handshake,task         ] Operation: RevokeOneBias for thread 0x000000000286d800, is_vm_thread: false, completed in 94800 ns
[5.723s][7248][debug][class,resolve          ] java.util.zip.ZipFile$CleanableResource java.lang.ref.Cleaner ZipFile.java:715
[5.723s][7248][debug][class,resolve          ] java.lang.ref.Cleaner jdk.internal.ref.CleanerImpl$PhantomCleanableRef Cleaner.java:220
[5.723s][7248][debug][class,resolve          ] java.util.zip.ZipFile$CleanableResource java.util.WeakHashMap ZipFile.java:716
...

Друга пауза трохи пізніше:

...
[6.246s][7248][info ][class,load              ] java.awt.Graphics source: jrt:/java.desktop
[6.246s][7248][debug][class,load              ]  klass: 0x0000000100081a00 super: 0x0000000100001080 loader: [loader data: 0x0000000002882bd0 of 'bootstrap'] bytes: 5625 checksum: 0025818f
[6.246s][7248][debug][class,resolve           ] java.awt.Graphics java.lang.Object (super)
[6.246s][7248][info ][class,loader,constraints] updating constraint for name java/awt/Graphics, loader 'bootstrap', by setting class object
[6.246s][7248][debug][jit,compilation         ]   19       4       java.lang.Object::<init> (1 bytes)   made not entrant
[6.246s][7248][debug][vmthread                ] Adding VM operation: HandshakeAllThreads
[6.246s][6708][debug][vmthread                ] Evaluating non-safepoint VM operation: HandshakeAllThreads
[6.246s][6708][debug][vmoperation             ] begin VM_Operation (0x000000000203ddf8): HandshakeAllThreads, mode: no safepoint, requested by thread 0x000000000286d800
[6.246s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x00000000026b0800, is_vm_thread: true, completed in 1400 ns
[6.246s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x00000000026bb800, is_vm_thread: true, completed in 700 ns
[6.246s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x00000000026ef800, is_vm_thread: true, completed in 100 ns
[6.246s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x00000000026f0800, is_vm_thread: true, completed in 100 ns
[6.246s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x00000000026f1800, is_vm_thread: true, completed in 100 ns
[6.246s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x00000000026f4800, is_vm_thread: true, completed in 100 ns
[6.247s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x0000000002768800, is_vm_thread: true, completed in 100 ns
[6.247s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x000000000276e000, is_vm_thread: true, completed in 100 ns
[6.247s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x0000000017268800, is_vm_thread: true, completed in 100 ns
[6.247s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x000000001727e800, is_vm_thread: true, completed in 800 ns

# no log until 11.783s

[11.783s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x000000000286d800, is_vm_thread: true, completed in 6300 ns
[11.783s][6708][info ][handshake               ] Handshake "Deoptimize", Targeted threads: 11, Executed by targeted threads: 0, Total completion time: 5536442500 ns
[11.783s][6708][debug][vmoperation             ] end VM_Operation (0x000000000203ddf8): HandshakeAllThreads, mode: no safepoint, requested by thread 0x000000000286d800
[11.783s][7248][debug][protectiondomain        ] Checking package access
[11.783s][7248][debug][protectiondomain        ] class loader: a 'jdk/internal/loader/ClassLoaders$AppClassLoader'{0x00000000c0058628} protection domain: a 'java/security/ProtectionDomain'{0x00000000c058b948} loading: 'java/awt/Graphics'
[11.783s][7248][debug][protectiondomain        ] granted
[11.783s][7248][debug][class,resolve           ] sun.launcher.LauncherHelper java.awt.Graphics LauncherHelper.java:816 (reflection)
[11.783s][7248][debug][class,resolve           ] jdk.internal.reflect.Reflection [Ljava.lang.reflect.Method; Reflection.java:300
[11.783s][7248][debug][class,preorder          ] java.lang.PublicMethods$MethodList source: C:\Users\example\AppData\Local\example\stable\jdk\lib\modules
...

Потім третій:

...
[14.578s][7248][debug][class,preorder          ] java.lang.InheritableThreadLocal source: C:\Users\example\AppData\Local\example\stable\jdk\lib\modules
[14.578s][7248][info ][class,load              ] java.lang.InheritableThreadLocal source: jrt:/java.base
[14.578s][7248][debug][class,load              ]  klass: 0x0000000100124740 super: 0x0000000100021a18 loader: [loader data: 0x0000000002882bd0 of 'bootstrap'] bytes: 1338 checksum: 8013ed55
[14.578s][7248][debug][class,resolve           ] java.lang.InheritableThreadLocal java.lang.ThreadLocal (super)
[14.578s][7248][debug][jit,compilation         ]  699       3       java.lang.ThreadLocal::get (38 bytes)   made not entrant
[14.578s][7248][debug][vmthread                ] Adding VM operation: HandshakeAllThreads
[14.578s][6708][debug][vmthread                ] Evaluating non-safepoint VM operation: HandshakeAllThreads
[14.578s][6708][debug][vmoperation             ] begin VM_Operation (0x000000000203d228): HandshakeAllThreads, mode: no safepoint, requested by thread 0x000000000286d800
[14.578s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x00000000026b0800, is_vm_thread: true, completed in 1600 ns
[14.578s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x00000000026bb800, is_vm_thread: true, completed in 900 ns
[14.578s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x00000000026ef800, is_vm_thread: true, completed in 100 ns
[14.578s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x00000000026f0800, is_vm_thread: true, completed in 100 ns
[14.578s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x00000000026f1800, is_vm_thread: true, completed in 100 ns
[14.578s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x00000000026f4800, is_vm_thread: true, completed in 0 ns
[14.578s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x0000000002768800, is_vm_thread: true, completed in 0 ns
[14.578s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x000000000276e000, is_vm_thread: true, completed in 0 ns
[14.578s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x0000000017268800, is_vm_thread: true, completed in 0 ns
[14.579s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x000000001727e800, is_vm_thread: true, completed in 900 ns

# no log until 21.455s

[21.455s][6708][debug][handshake,task          ] Operation: Deoptimize for thread 0x000000000286d800, is_vm_thread: true, completed in 12100 ns
[21.455s][6708][info ][handshake               ] Handshake "Deoptimize", Targeted threads: 11, Executed by targeted threads: 0, Total completion time: 6876829000 ns
[21.455s][6708][debug][vmoperation             ] end VM_Operation (0x000000000203d228): HandshakeAllThreads, mode: no safepoint, requested by thread 0x000000000286d800
[21.455s][7248][debug][class,resolve           ] sun.security.jca.Providers java.lang.InheritableThreadLocal Providers.java:39
[21.455s][7248][info ][class,init              ] 1251 Initializing 'java/lang/InheritableThreadLocal'(no method) (0x0000000100124740)
[21.455s][7248][debug][class,resolve           ] java.lang.InheritableThreadLocal java.lang.ThreadLocal InheritableThreadLocal.java:57
[21.456s][7248][debug][class,preorder          ] sun.security.jca.ProviderList source: C:\Users\example\AppData\Local\example\stable\jdk\lib\modules
[21.456s][7248][info ][class,load              ] sun.security.jca.ProviderList source: jrt:/java.base
[21.456s][7248][debug][class,load              ]  klass: 0x00000001001249a8 super: 0x0000000100001080 loader: [loader data: 0x0000000002882bd0 of 'bootstrap'] bytes: 11522 checksum: bdc239d2
[21.456s][7248][debug][class,resolve           ] sun.security.jca.ProviderList java.lang.Object (super)
...

Наступні два рядки здаються цікавими:

[11.783s][6708][info ][handshake               ] Handshake "Deoptimize", Targeted threads: 11, Executed by targeted threads: 0, Total completion time: 5536442500 ns
[21.455s][6708][info ][handshake               ] Handshake "Deoptimize", Targeted threads: 11, Executed by targeted threads: 0, Total completion time: 6876829000 ns

Це нормально, що на ці рукостискання знадобилося 5,5 і 6,8 секунди?

У мене спостерігалося таке ж уповільнення (і подібні журнали) з демо-програмою update4j (яка абсолютно не пов'язана з нашою програмою), що працює з цією командою:

Z:\swing>\jdk-14\bin\java -Xlog:all=debug:file=app.txt:uptime,tid,level,tags:filecount=50 \
    -jar update4j-1.4.5.jar --remote http://docs.update4j.org/demo/setup.xml

На що слід звернути увагу, щоб зробити наш додаток швидшим у налаштуваннях Windows 10 з одним процесором? Чи можна це виправити, змінивши щось у нашій програмі або додавши аргументи JVM?

Це помилка JDK, я повинен повідомити про це?

оновлення 2020-04-25:

Наскільки я бачу, файли журналів також містять журнали GC. Це перші журнали GC:

$ cat app.txt.00 | grep "\[gc"
[0.016s][7248][debug][gc,heap          ] Minimum heap 8388608  Initial heap 60817408  Maximum heap 1073741824
[0.017s][7248][info ][gc,heap,coops    ] Heap address: 0x00000000c0000000, size: 1024 MB, Compressed Oops mode: 32-bit
[0.018s][7248][info ][gc               ] Using Serial
[22.863s][6708][info ][gc,start                ] GC(0) Pause Young (Allocation Failure)
[22.863s][6708][debug][gc,heap                 ] GC(0) Heap before GC invocations=0 (full 0): def new generation   total 17856K, used 15936K [0x00000000c0000000, 0x00000000c1350000, 0x00000000d5550000)
...

На жаль, це не здається пов'язаним, оскільки воно починається після третьої паузи.

оновлення 2020-04-26:

З OpenJDK 14 програма використовує 100% ЦП у моїй (однопроцесорній) машині VirtualBox (працює на процесорі i7-6600U). Віртуальна машина має 3,5 ГБ оперативної пам’яті. За даними диспетчера завдань, 40% + є безкоштовним, а дискова активність - 0% (я думаю, це означає відсутність заміни). Додавання іншого віртуального процесора до віртуальної машини (та ввімкнення гіпернарізки для фізичних машин) зробить додаток досить швидким. Мені просто цікаво, чи було навмисним компромісом під час розробки JDK втратою продуктивності на (рідкісних) машинах з одним процесором, щоб зробити JVM швидше на багатоядерних / гіпер-потокових процесорах?


3
Чи -Xlog:all=debugвключається реєстрація в GC? Це мій перший здогад про будь-які паузи.
кічик

Ви спробували працювати з профілером і порівняти результати? Я думаю, що це було б природно.
Аксель

1
також перегляньте системні повідомлення Windows, спробуйте іншу збірку для jdk 14. Якщо все інше не вдається, ескалація стане проблемою?
Khanna111

1
@ Yan.F: OpenJDK 11 не буде підтримуватися вічно, саме час підготувати нові випуски та помилки. Крім того, видається помилка JDK - яка може бути виправлена ​​чи ні, але також може допомогти іншим. У всякому разі, для мене це здебільшого цікавість. З іншого боку, я хотів би зараз сказати нашим клієнтам як мінімальні системні вимоги нашої програми.
palacsint

1
@ Khanna111: Так, я щойно написав це як відповідь.
палацинт

Відповіді:


6

З мого досвіду проблеми з роботою JDK в основному пов'язані з одним із наступних:

  • Компіляція JIT
  • Конфігурація VM (розміри купи)
  • Алгоритм ГК
  • Зміни в JVM / JDK, які порушують відомі хороші запущені програми
  • (О, і я забув згадати завантаження класу ...)

Якщо ви просто використовуєте конфігурацію JVM за замовчуванням з OpenJDK11, можливо, вам слід встановити деякі більш помітні параметри фіксованим значенням, наприклад, GC, розмір Heap тощо.

Можливо, якийсь інструмент для графічного аналізу може допомогти відстежити вашу проблему. Як і Retrace, AppDynamics або FlightRecorder тощо. Вони дають більший огляд загального стану купи, циклів gc, оперативної пам’яті, потоків, завантаження процесора тощо за певний час, ніж файли журналів могли забезпечити.

Я правильно розумію, що ваша програма записує близько 30710 рядків у журнал протягом першої секунди запуску (під OpenJDK11)? Чому в першій секунді "лише" писати близько 7k рядків під OpenJDK14? Це здається величезною різницею для програми, яка щойно запущена на різних JVM-кодах для мене ... Ви впевнені, що немає, наприклад, великої кількості стек-треків винятків, скинутих у журнал?
Інші цифри іноді навіть вищі, тому, можливо, уповільнення пов'язані з реєстрацією винятків? Або навіть обмінятися, якщо оперативна пам’ять знизиться?
Насправді я думаю, якщо додаток нічого не записує в журнал, це ознака безперебійного запуску без проблем (якщо тільки він повністю не заморожений за цей час). Що відбувається з 12-22 секунд (у випадку OpenJDK14 тут) - це те, що би мене більше хвилювало ... ліній, що зареєстровані, проходять крізь дах ... чому ?
А потім лісозаготівельної спускається весь час низьких значень близько 1-2k ліній ... що є причиною , що ?? (ну, може, саме GC починає о 22-й і робить табула-rasa, яка вирішує деякі речі ...?)

Іншою справою може стати ваша заява про машини "єдиного процесора". Чи означає це також "єдине ядро" (Idk, можливо, ваше програмне забезпечення підходить під застаріле обладнання або щось подібне)? І VM на "єдиному процесорі" працюють на цих машинах? Але я припускаю, що я помиляюся в цих припущеннях, оскільки майже всі процесори сьогодні є багатоядерними ... але, можливо, я би розслідував проблему з багатопотоковою (тупиковою ситуацією).


2
Будь ласка, не використовуйте підписи або теги в своїх дописах, повторювані "GL і HF" вважаються шумом і відволіканням від вмісту вашої публікації тут. Для отримання додаткової інформації див. Meta.stackexchange.com/help/behavior .
meagar

1
"Я правильно розумію, що ваша програма записує близько 30710 рядків у журнал протягом першої секунди запуску (під OpenJDK11)?" - Так, ви праві.
palacsint

1
"Ви впевнені, що, наприклад, у журнал не завантажено велику кількість стек-трак винятків?" - Журнал чистий, я нічого дивного там не знайшов, програма працює коректно (за винятком того, що він працює дуже-дуже повільно).
palacsint

1
GC б'є на 22-й секунді, і додаток залишається повільним після цього. Я також оновив питання. Зауважте, що демонстраційний додаток update4j також має ту саму проблему. Дякую за відповідь!
palacsint

1
30k + рядки журналів за одну секунду досить величезні ... ти не згоден? Мені дуже цікаво, що може бути корисним для входу в систему, щоб прийняти таку велику кількість ліній журналів за такий короткий час ... Ви спробували повністю вимкнути журнал і профайлювати додаток у цьому режимі? (Мені цікаво, але, можливо, реєстрація справді не впливає, як ви маєте на увазі поведінку update4j)
Antares

5

Оскільки він використовує 100% ЦП "більшу частину часу", і це займає в Java 10 разів більше (!), Це означає, що ви витрачаєте 90% свого процесора на Java 14.

Вичерпання простору купи може це зробити, оскільки ви проводите багато часу в GC, але ви, здається, це виключили.

Я помічаю, що ви налаштовуєте упереджений варіант блокування, і це робить суттєву зміну. Це говорить мені, що, можливо, ваша програма виконує багато одночасних робіт у кількох потоках. Можливо, що у вашій програмі є помилка одночасності, яка відображається на Java 14, але не в Java 10. Це також може пояснити, чому додавання іншого процесора робить його більш ніж удвічі швидшим.

Помилки паралельної валюти часто з’являються лише тоді, коли вам не пощастило, і тригером дійсно могло бути що завгодно, як-от зміна організації хешмапу тощо

По-перше, якщо це можливо, перевірте, чи є петлі, які можуть бути зайняті-чекати замість сну.

Потім запустіть профілер у режимі вибірки (jvisualvm зробить) і шукайте методи, які займають набагато більший% від загального часу, ніж повинні. Оскільки ваша продуктивність знижується на 10, будь-які проблеми там дійсно повинні вискочити.


Упереджене блокування було необхідне в минулому, але в наш час не так багато, і його пропонується відключити за замовчуванням і пізніше видалити: openjdk.java.net/jeps/374
JohannesB

2

Це цікаве питання, і це потребує невизначеної кількості зусиль, щоб зменшити його, оскільки існує багато перестановок та комбінацій, які потрібно випробувати, а також зібрати та зібрати дані.

Здається, що вже давно не було вирішено цього питання. Можливо, це може бути необхідним для збільшення рівня.

EDIT 2: Оскільки "ThreadLocalHandshakes" застарілий, і ми можемо припустити, що блокування спростовується, запропонуйте спробувати без "UseBiasedLocking", щоб сподіватися прискорити цей сценарій.

Однак є кілька пропозицій зібрати більше даних та спробувати вирішити проблему.

  1. Виділіть більше одного ядра [я бачу, що ви спробували це, і проблема відходить. Здається, проблема з виконанням потоку / с виключає інші. Дивіться не 7 нижче)
  2. Виділіть більше купи (можливо, вимоги v14 більше, ніж у попередніх jdks)
  3. Виділіть більше пам'яті для Win 10 VB.
  4. Перевірте системні повідомлення ОС (виграйте 10 у вашому випадку)
  5. Запустіть його у невіртуалізованому Win 10.
  6. Спробуйте іншу збірку jdk 14
  7. Робіть скидання ниток кожні (або профіль) через кілька інтервалів часу. Проаналізуйте, яка нитка працює виключно. Можливо, є налаштування для справедливого розподілу часу. Можливо, працює нитка більшого пріоритету. Що це за нитка і що вона робить? У linux ви могли стати статистикою легких процесів (потоків), пов'язаних з процесом та його станом у режимі реального часу. Щось схоже на Win 10?
  8. Використання процесора? 100% чи менше? Обмежений процесором чи пам'яттю? 100% ЦП в сервісних потоках? Яка службова нитка?
  9. Ви явно встановили альго GC?

Я особисто був свідком проблем у версіях, які стосуються GC, набору розмірів, проблем з віртуалізованими контейнерами тощо.

Думаю, що на це немає простої відповіді, тим більше, що це питання існує вже деякий час. Але ми можемо спробувати все найкраще і повідомити нам, що є результатом деяких із цих етапів ізоляції.

EDIT 1: з оновленого питання, схоже, це пов’язано з GC або іншою службовою ниткою, яка нерівноправно переймає одне ядро ​​(Thread-Local Handshakes)?


Додавання додаткового ядра центрального процесора, що використовується для запуску переходу з ергономіки Java в 32-бітових системах від клієнта до сервера класу vm з різними GC та багаторівневою компіляцією, якщо це все ще так, це може пояснити раптові відмінності у продуктивності та використанні пам'яті, так JVM виступ складний 😁
ЙоханнесB

3
Ергономіка Java (налаштування за замовчуванням) все ще відрізняється для 1 процесора (наприклад: -XX: + UseSerialGC) або 2 процесора (наприклад: G1GC, LoopStripMiningIter = 1000, ... ShortLoop = 100), але після того, як переконайтеся, що з -XX: + PrintFlagsFinal, що я налаштував усі параметри на той самий або подібний запущений update4j, все ще був надзвичайно повільним, починаючи лише з одного замість 2 процесора з cmd.exe / C start / афінністю 0x1 (але надзвичайно швидко з 0x3 - таким чином використовуючи 2 cpus (1 + 10 двійкових)). Я підтвердив, що ми не можемо звинувачувати жодного сміттєзбірника, використовуючи Epsilon GC, який призначений для уникнення накладних витрат на GC. Тимчасова компіляція ввімкнена
JohannesB

Розумію. З Epsilon GC здається, що це було так само повільно. У цьому випадку стану ниток та скидів, щоб оцінити, де він застряє, може бути способом. І в Java Java, і в світі ОС (Linux, якщо я пам'ятаю, був gcore)
Khanna111,

2

TL; DR : Регресія OpenJDK.

Я не тільки цього, але міг відтворити проблему простим привітним світом:

public class Main {
    public static void main(String[] args) {
        System.out.println("Hello world");
    }
}

Я використав ці два пакетні файли:

main-1cpu.bat, що обмежує javaпроцес лише одним процесором:

c:\windows\system32\cmd.exe /C start /affinity 1 \
    \jdk-14\bin\java \
    -Xlog:all=trace:file=app-1cpu.txt:uptime,tid,level,tags:filecount=50 \
    Main

main-full.bat, javaпроцес може використовувати обидва процесори:

c:\windows\system32\cmd.exe /C start /affinity FF \
    \jdk-14\bin\java \
    -Xlog:all=trace:file=app-full.txt:uptime,tid,level,tags:filecount=50 \
    Main

(Відмінності полягають у affinityзначенні та назві файлу журналу. Я обгорнув його для легшого читання, але обгортання\ мабуть, не працює в Windows.)

Кілька вимірювань у Windows 10 x64 у VirtualBox (з двома процесорами):

PS Z:\main> Measure-Command { .\main-1cpu.bat }

...    
TotalSeconds      : 7.0203455
...


PS Z:\main> Measure-Command { .\main-full.bat }

...
TotalSeconds      : 1.5751352
...


PS Z:\main> Measure-Command { .\main-full.bat }

...
TotalSeconds      : 1.5585384
...


PS Z:\main> Measure-Command { .\main-1cpu.bat }

...
TotalSeconds      : 23.6482685
...

Вироблені траєктологи містять подібні паузи, які ви можете побачити у питанні.

Запуск Mainбез мікроконтролерів відбувається швидше, але різницю все одно можна побачити між версією одного процесора та двома процесорами: ~ 4-7 секунд проти ~ 400 мс.

Я надіслав ці висновки до списку розсилки hotspot-dev @ openjdk, і там розроблені розробники підтвердили, що JDK може краще впоратися . Ви також можете знайти виправлені помилки в потоці. Сподіваємось, це буде зафіксовано у OpenJDK 15.


Дякуємо за відгук!
Антарес

1

Будьте уважні до входу в систему для повільних дисків, це сповільнить вашу програму:

https://engineering.linkedin.com/blog/2016/02/elimining-large-jvm-gc-pauses-cause-by-background-io-traffic

Але це, мабуть, не стане причиною проблеми, оскільки процесор все ще зайнятий, і вам не доведеться чекати, поки всі потоки прийдуть до безпечної точки завдяки локальному рукостисканню з потоком: https: // openjdk. java.net/jeps/312

Крім того, що не пов'язане безпосередньо з проблемою, яка виникає, але в більш загальному випадку, якщо ви хочете спробувати вичавити більшу продуктивність зі свого обладнання на час запуску, подивіться на AppCDS (обмін даними класу):

https://blog.codefx.org/java/application-class-data-sharing/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.