단일 CPU 설정 및 Java 12+로 인해 응용 프로그램이 느려지고 JVM이 자주 중단됨


23

우리는 클라이언트 응용 프로그램을 가지고 있습니다 (10 년 이상의 개발 경험) JDK는 최근 OpenJDK 11에서 OpenJDK 14로 업그레이드되었습니다. 단일 CPU (하이퍼 스레딩 비활성화 됨) Windows 10 설정 (및 사용 가능한 CPU가 하나만있는 VirtualBox 시스템 내)에서 응용 프로그램은 Java 11에 비해 상당히 느리게 시작됩니다. 또한 대부분 100 % CPU를 사용합니다. 프로세서 선호도를 하나의 CPU ( 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 with -XX:-UseBiasedLocking: 46 초
  • OpenJDK 13.0.2 -XX:-ThreadLocalHandshakes: 40 초
  • OpenJDK 14 : 5-6 분
  • OpenJDK 14 포함 -XX:-UseBiasedLocking: 3-3,5 분
  • OpenJDK 15 EA 빌드 20 : ~ 4,5 분

사용 된 JDK (및 언급 된 옵션) 만 변경되었습니다. ( -XX:-ThreadLocalHandshakesJava 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

단일 CPU 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에서 응용 프로그램은 내 (단일 CPU) VirtualBox 시스템 (i7-6600U CPU에서 실행)에서 100 % CPU를 사용합니다. 가상 머신에는 3,5GB RAM이 있습니다. 작업 관리자에 따르면 40 % +는 사용 가능하고 디스크 활동은 0 %입니다 (스왑이 없음을 의미합니다). 가상 머신에 다른 CPU를 추가하고 물리적 머신에 대한 하이퍼 스레딩을 활성화하면 애플리케이션을 다시 빠르게 실행할 수 있습니다. JDK 개발 중에 단일 CPU 시스템의 성능을 잃어 멀티 코어 / 하이퍼 스레딩 CPU에서 JVM을 더 빠르게 만들기 위해 의도적으로 절충 했습니까?


3
않습니다 -Xlog:all=debugGC 로깅을 설정? 그것은 일시 중지에 대한 첫 번째 추측입니다.
kichik

프로파일 러로 실행을 시도하고 결과를 비교 했습니까? 나는 그것이 자연스런 일이라고 생각합니다.
Axel

1
또한 Windows 시스템 메시지를 확인하고 jdk 14에 대해 다른 빌드를 시도하십시오. 다른 모든 방법이 실패하면 문제로 에스컬레이션 하시겠습니까?
Khanna111

1
@ Yan.F : OpenJDK 11은 영원히 지원되지 않습니다. 이제 새로운 릴리스와 버그를 준비해야합니다. 또한 JDK 버그 인 것 같습니다. 수정 될 수도 있고 아닐 수도 있습니다. 어쨌든, 나를 위해 그것은 대부분 호기심입니다. 반면에 이제는 앱의 최소 시스템 요구 사항으로 고객에게 무엇을 말하고 싶습니까?
palacsint

1
@ Khanna111 : 예, 방금 답변으로 작성했습니다.
palacsint

답변:


6

내 경험에 따르면 JDK의 성능 문제는 주로 다음 중 하나와 관련이 있습니다.

  • JIT 컴파일
  • VM 구성 (힙 크기)
  • GC 알고리즘
  • 알려진 실행중인 응용 프로그램을 손상시키는 JVM / JDK의 변경
  • (아, 그리고 클래스 로딩을 언급하는 것을 잊었다 ...)

OpenJDK11 이후 기본 JVM 구성 만 사용하는 경우 GC, 힙 크기 등과 같은 더 눈에 띄는 옵션 중 일부를 고정 된 값으로 설정해야합니다.

그래픽 분석 도구가 문제를 추적하는 데 도움이 될 수 있습니다. Retrace, AppDynamics 또는 FlightRecorder 등과 유사합니다. 로그 파일이 제공 할 수있는 것보다 주어진 시간에 힙, gc주기, RAM, 스레드, CPU로드 등의 전체 상태에 대한 자세한 개요를 제공합니다.

애플리케이션이 OpenJDK11 하에서 실행 후 1 초 이내에 로그에 약 30710 라인을 기록한다는 것을 올바르게 알고 있습니까? 왜 첫 번째 초에 OpenJDK14에서 약 7k 라인을 쓰는 것입니까? 이것은 다른 JVM에서 방금 시작된 응용 프로그램의 경우 큰 차이처럼 보입니다. 예를 들어 로그에 많은 양의 예외 스택 추적이 덤프되지 않았습니까?
다른 숫자는 때때로 더 높으므로 속도 저하가 예외 로깅과 관련이 있습니까? 또는 RAM이 부족하면 스와핑?
실제로 응용 프로그램이 로그에 아무것도 쓰지 않으면 문제없이 부드럽게 실행되는 징후입니다 (이 시점에서 완전히 동결되지 않은 경우). 12-22 초 (OpenJDK14의 경우)에서 일어나는 일은 저에게 더 관심이있는 것입니다 ... 기록 된 선이 지붕을 통과합니다 ... ?
그리고 나중에 로깅에 대한 이유 무엇인가 ... 1-2k에 대한 라인의 모든 시간 낮은 값으로 내려 간다 ? (글쎄, 어쩌면 22 초에 gc가 시작되고 어떤 것들을 해결하는 타블라 라사를 수행합니까 ...?)

"단일 CPU"머신에 대한 진술 일 수도 있습니다. 이것이 "단일 코어"를 의미합니까 (Idk, 소프트웨어가 레거시 하드웨어 또는 기타에 맞춰져있을 수 있습니다)? 그리고 "단일 CPU"VM이 해당 머신에서 실행되고 있습니까? 그러나 요즘 거의 모든 CPU가 멀티 코어이기 때문에 이러한 가정에 대해 잘못 생각합니다 ...하지만 멀티 스레딩 문제 (교착 상태) 문제에 대해 조사 할 것입니다.


2
게시물에 서명이나 태그 라인을 사용하지 마십시오. 반복적 인 "GL 및 HF"는 여기에서 게시물의 내용에 방해가되고 소음으로 간주됩니다. 자세한 내용은 meta.stackexchange.com/help/behavior 를 참조하십시오.
meagar

1
"응용 프로그램이 OpenJDK11에서 실행 후 1 초 이내에 로그에 약 30710 행을 기록한다는 것을 올바르게 알고 있습니까?" - 네 말이 맞아.
palacsint

1
"예를 들어 로그에 많은 양의 예외 스택 추적이 덤프되지 않았습니까?" -로그가 깨끗하고 이상한 것을 발견하지 못했으며 응용 프로그램이 올바르게 작동합니다 (매우 느리게 실행되는 것을 제외하고).
palacsint

1
GC는 22 초 만에 시작되고 그 이후에도 앱은 느려집니다. 또한 질문을 업데이트했습니다. update4j 데모 앱에도 동일한 문제가 있습니다. 응답 해주셔서 감사합니다!
palacsint

1
1 초에 30k + 이상의 로그 라인은 상당히 크지 만 동의하지 않습니까? 짧은 시간에 많은 양의 로그 라인을 수용하기 위해 무엇이 로그에 기록 될 수 있는지 궁금합니다. 로깅을 완전히 해제하고이 모드에서 응용 프로그램을 프로파일 링하셨습니까? (호기심이 많지만 update4j 동작으로 암시하는 것처럼 로깅은 실제로 영향을 미치지 않습니다.)
Antares

5

100 % CPU를 "대부분"사용하고 있고 Java 14에서는 10 배 더 오래 걸립니다 (!). 이는 Java 14에서 CPU의 90 %를 낭비하고 있음을 의미합니다.

GC에서 많은 시간을 보내면서 힙 공간이 부족 하면 그렇게 할 수 있지만 배제한 것 같습니다.

바이어스 잠금 옵션을 조정하고 있으며 큰 차이가 있습니다. 그것은 아마도 귀하의 프로그램이 여러 스레드에서 많은 동시 작업을 수행한다는 것을 알려줍니다. 프로그램에 Java 14에는 나타나지만 Java 10에는 나타나지 않는 동시성 버그가있을 수 있습니다. 또한 다른 CPU를 추가하면 2 배 이상 빠르는 이유를 설명 할 수 있습니다.

동시성 버그는 종종 운이 좋지 않을 때만 나타나며 트리거는 실제로 해시 맵 구성 변경과 같은 것일 수 있습니다.

먼저 가능한 경우, 잠자기 대신 사용 중일 수있는 루프가 있는지 확인하십시오.

그런 다음 샘플링 모드에서 프로파일 러를 실행하고 (jvisualvm이 수행함) 총 시간의 훨씬 더 많은 시간이 걸리는 메소드를 찾으십시오. 성능이 10 배나 떨어 지므로 문제가 실제로 발생합니다.


과거에는 바이어스 잠금이 필요했지만 현재는 그리 많지 않으며 기본적으로 비활성화되어 나중에 제거되는 것이 좋습니다
JohannesB

2

이것은 흥미로운 문제이며 시도하고 데이터를 수집하고 수집해야하는 순열과 조합이 많기 때문에이를 좁히기 위해서는 많은 노력이 필요합니다.

한동안 이것에 대한 해결책이 없었던 것 같습니다. 아마도이 단계를 확대해야 할 수도 있습니다.

편집 2 : "ThreadLocalHandshakes"는 더 이상 사용되지 않으며 잠금이 문제가 있다고 가정 할 수 있으므로 "UseBiasedLocking"없이 시도하면이 시나리오의 속도를 높일 수 있습니다.

그러나 더 많은 데이터를 수집하고 문제를 격리하려는 몇 가지 제안이 있습니다.

  1. 둘 이상의 코어를 할당하십시오. 시도해 보았고 문제는 사라졌습니다. 다른 사람을 배제하는 스레드 실행에 문제가있는 것 같습니다. 아래 7 참조)
  2. 더 많은 힙 할당 (아마도 v14의 요구가 이전 jdk의 요구보다 많은 경우)
  3. Win 10 VB에 더 많은 메모리를 할당하십시오.
  4. OS 시스템 메시지 확인 (귀하의 경우 10 번 승리)
  5. 가상화되지 않은 Win 10에서 실행하십시오.
  6. jdk 14의 다른 빌드를 사용해보십시오
  7. 몇 시간 간격마다 스레드 덤프를 수행하십시오. 어떤 스레드가 독점적으로 실행 중인지 분석하십시오. 공평한 시간 공유를위한 설정이있을 수 있습니다. 우선 순위가 높은 스레드가 실행 중일 수 있습니다. 그 스레드는 무엇이며 무엇을하고 있습니까? 리눅스에서는 프로세스 및 프로세스 상태와 관련된 간단한 프로세스 (스레드)를 실시간으로 통계 할 수 있습니다. Win 10에서 비슷한 점이 있습니까?
  8. CPU 사용량? 100 % 이하? CPU 또는 mem에 의해 제한됩니까? 서비스 스레드에서 100 % CPU? 어떤 서비스 스레드?
  9. GC 알고리즘을 명시 적으로 설정 했습니까?

GC, 힙 크기 조정, 가상화 컨테이너 문제 등과 관련된 버전 내의 문제를 개인적으로 목격했습니다.

그 질문에 대한 대답은 쉽지 않습니다. 특히이 질문은 한동안 진행 되었기 때문입니다. 그러나 최선을 다해 이러한 격리 단계의 결과를 알려줄 수 있습니다.

편집 1 : 업데이트 된 질문에서 단일 코어를 불균등하게 인수하는 GC 또는 다른 서비스 스레드와 관련이있는 것 같습니다 (스레드 로컬 핸드 셰이크)?


32 비트 시스템에서 Java 인체 공학에서 클라이언트에서 서버 클래스 vm으로 다른 GC 및 계층 컴파일을 사용하여 서버 성능과 메모리 사용량의 갑작스러운 차이를 설명 할 수있는 경우 추가 CPU 코어 추가 (예 : JVM) 성능이 복잡함 😁
JohannesB

3
Java 인체 공학 (기본 설정)은 CPU 1 개 (예 : -XX : + UseSerialGC) 또는 CPU 2 개 (예 : G1GC, LoopStripMiningIter = 1000, ... ShortLoop = 100)에 대해 여전히 다르지만 -XX : +로 확인한 후 내가 cmd.exe / C start / affinity 0x1을 사용하여 2 CPU 대신 하나의 CPU로 시작하는 모든 매개 변수를 동일하거나 유사한 것으로 변경했습니다 .FinFlagsFinals (4 + 10 이진)). GC 오버 헤드를 피하도록 설계된 Epsilon GC를 사용하여 가비지 수집기를 비난 할 수 없음을 확인했습니다. 그러나 TieredCompilation을 사용할 수 있습니다
JohannesB

내가 참조. Epsilon GC를 사용하면 마치 느린 것처럼 보입니다. 이 경우 스레드 상태 및 덤프 위치를 파악하기위한 방법이 될 수 있습니다. 자바 세계와 OS 세계 (내가 기억한다면 리눅스)
Khanna111

2

TL; DR : OpenJDK 회귀입니다.

나는 그것을 제외하지 않았지만 간단한 hello world로 문제를 재현 할 수 있습니다.

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

이 두 배치 파일을 사용했습니다.

main-1cpu.batjava프로세스를 하나의 CPU로만 제한합니다 .

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.batjava과정은 모두 CPU를 사용할 수 있습니다 :

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에서는 줄 바꿈이 작동하지 않을 수 있습니다.)

VirtualBox의 Windows 10 x64에서 몇 가지 측정 (CPU 2 개) :

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추적 로그없이 실행하는 것이 더 빠르지 만 단일 CPU 버전과 2 CPU 버전의 차이는 ~ 4-7 초 대 ~ 400ms입니다.

이 결과를 hotspot-dev @ openjdk 메일 목록으로 보냈고 개발자 들은 이것이 JDK가 더 잘 처리 할 수있는 것임을 확인했습니다 . 스레드에서도 가정 된 수정 사항 을 찾을 수 있습니다 . 바라건대 OpenJDK 15에서 수정 될 것입니다.


1

디스크 속도를 느리게 기록하면 응용 프로그램 속도가 느려집니다.

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

그러나 CPU가 여전히 사용 중이므로 스레드 로컬 핸드 셰이크 덕분에 모든 스레드가 안전한 지점에 올 때까지 기다릴 필요가 없습니다 ( https : // openjdk). java.net/jeps/312

또한 문제와 직접 관련이 없지만 시작 시간 동안 하드웨어에서 더 많은 성능을 끌어 내려면 AppCDS (클래스 데이터 공유)를 살펴보십시오.

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.