धीमी गति से अनुप्रयोग, लगातार JVM सिंगल-सीपीयू सेटअप और जावा 12+ के साथ हैंग होता है


23

हमारे पास एक ग्राहक अनुप्रयोग है (विकास के 10+ वर्षों के साथ)। इसका JDK हाल ही में OpenJDK 11 से OpenJDK 14 में अपग्रेड किया गया था। सिंगल-सीपीयू (हाइपर-थ्रेडिंग डिसेबल) विंडोज 10 सेटअप (और केवल एक उपलब्ध सीपीयू के साथ वर्चुअलबॉक्स मशीनों के अंदर) जावा 11 की तुलना में एप्लिकेशन बहुत धीरे-धीरे शुरू होता है। इसके अलावा, यह ज्यादातर समय 100% सीपीयू का उपयोग करता है। हम प्रोसेसर की आत्मीयता को केवल एक सीपीयू ( c:\windows\system32\cmd.exe /C start /affinity 1 ...) में सेट करने के साथ समस्या को भी पुन: उत्पन्न कर सकते हैं ।

आवेदन शुरू करने और मेरे VirtualBox मशीन में न्यूनतम मैनुअल इंटरैक्शन के साथ एक क्वेरी करने के साथ कुछ माप:

  • ओपनजेडके 11.0.2: 36 सेकंड
  • OpenJDK 13.0.2: ~ 1.5 मिनट
  • OpenJDK 13.0.2 के साथ -XX:-UseBiasedLocking: 46 सेकंड
  • OpenJDK 13.0.2 के साथ -XX:-ThreadLocalHandshakes: 40 सेकंड
  • ओपनजेडके 14: 5-6 मिनट
  • OpenJDK 14 के साथ -XX:-UseBiasedLocking: 3-3,5 मिनट
  • ओपनजेडके 15 ईए बिल्ड 20: ~ 4,5 मिनट

केवल प्रयुक्त JDK (और उल्लिखित विकल्प) को बदल दिया गया है। ( -XX:-ThreadLocalHandshakesजावा 14 में उपलब्ध नहीं है)

हमने लॉगिंग करने की कोशिश की है कि जेडीके 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 सेकंड लगे?

मैंने इस कमांड के साथ चल रहे अपडेट 4j डेमो ऐप (जो हमारे एप्लिकेशन से पूरी तरह से असंबंधित है ) के साथ एक ही मंदी (और समान लॉग) का अनुभव किया है:

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

सिंगल-सीपीयू विंडोज 10 सेटअप पर फिर से हमारे ऐप को फिर से तेज़ बनाने के लिए मुझे क्या देखना चाहिए? क्या हम इसे हमारे एप्लिकेशन में कुछ बदलकर या JVM तर्कों को जोड़कर ठीक कर सकते हैं?

क्या वह JDK बग है, मुझे इसकी रिपोर्ट करनी चाहिए?

अद्यतन 2020-04-25:

जहाँ तक मुझे लगता है कि लॉग फाइलें भी जीसी लॉग होती हैं। ये पहली 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 के साथ एप्लीकेशन मेरे (सिंगल-सीपीयू) वर्चुअलबॉक्स मशीन (i7-6600U CPU पर चलने) में 100% CPU का उपयोग करता है। वर्चुअल मशीन में 3,5 जीबी रैम है। टास्क मैनेजर के अनुसार 40% + मुफ़्त है और डिस्क गतिविधि 0% है (मुझे लगता है कि इसका मतलब है कोई स्वैपिंग नहीं है)। वर्चुअल मशीन में एक और सीपीयू जोड़ना (और भौतिक मशीनों के लिए हाइपर-थ्रेडिंग को सक्षम करना) एप्लिकेशन को फिर से तेजी से बनाता है। मैं बस सोच रहा था, क्या यह JDK विकास के दौरान जानबूझकर व्यापार बंद था (दुर्लभ) सिंगल-सीपीयू मशीनों पर जेवीएम को मल्टीकोर / हाइपर-थ्रेडिंग सीपीयू पर तेज करने के लिए?


3
-Xlog:all=debugजीसी लॉगिंग चालू करता है ? किसी भी ठहराव के लिए यह मेरा पहला अनुमान होगा।
किचिक

क्या आपने एक प्रोफाइलर के साथ चलने और परिणामों की तुलना करने की कोशिश की? मुझे लगता है कि ऐसा करना स्वाभाविक बात होगी।
एक्सल

1
विंडोज़ सिस्टम संदेशों की भी जांच करें, jdk 14. के लिए एक अलग बिल्ड की कोशिश करें। यदि अन्य सभी विफल हो जाते हैं, तो एक मुद्दे के रूप में आगे बढ़ें?
खन्ना ११

1
@ यान.एफ: ओपनजेडके 11 हमेशा के लिए समर्थित नहीं होगा, यह नई रिलीज और बग तैयार करने का समय है। इसके अलावा, यह JDK बग लगता है - जो तय हो सकता है या नहीं, लेकिन दूसरों की भी मदद कर सकता है। वैसे भी, मेरे लिए यह ज्यादातर उत्सुकता है। दूसरी ओर मैं अब अपने ग्राहकों को हमारे ऐप की न्यूनतम प्रणाली आवश्यकताओं के रूप में बताना चाहूंगा।
पालकी

1
@ खन्ना ११: हाँ, मैंने इसे उत्तर के रूप में लिखा है।
पैलसिंट

जवाबों:


6

JDKs के साथ मेरे अनुभव के प्रदर्शन की समस्याओं में से ज्यादातर निम्नलिखित में से एक से संबंधित हैं:

  • JIT संकलन
  • वीएम कॉन्फ़िगरेशन (ढेर आकार)
  • जीसी एल्गोरिदम
  • JVM / JDK में बदलाव जो ज्ञात अच्छे चलने वाले अनुप्रयोगों को तोड़ते हैं
  • (ओह, और मैं क्लास लोडिंग का उल्लेख करना भूल गया ...)

यदि आप OpenJDK11 के बाद से बस डिफ़ॉल्ट JVM कॉन्फ़िगरेशन का उपयोग करते हैं, तो शायद आपको निश्चित मानों में से कुछ प्रमुख विकल्पों को सेट करना चाहिए, जैसे जीसी, हीप आकार, आदि।

हो सकता है कि कुछ ग्राफिकल विश्लेषण उपकरण आपकी समस्या को ट्रैक करने में मदद कर सके। रिट्रेस, ऐपडायरेक्टिक्स या फ्लाइटक्रैकर और पसंद है। ये ढेर की समग्र स्थिति पर अधिक अवलोकन देते हैं, जीसी चक्र, रैम, थ्रेड्स, सीपीयू लोड और इतने पर एक निश्चित समय पर लॉग फाइल प्रदान कर सकते हैं।

क्या मैं सही ढंग से समझता हूं कि आपका एप्लिकेशन रनिंग के पहले सेकंड के भीतर लॉग में (OpenJDK11 के तहत) 30710 लाइनें लिखता है? यह पहले सेकंड में OpenJDK14 के तहत 7k लाइनों के बारे में "केवल" क्यों लिख रहा है? यह उस एप्लिकेशन के लिए एक बहुत बड़ा अंतर लगता है जो अभी मेरे लिए अलग-अलग JVM पर शुरू हुआ है ... क्या आप सुनिश्चित हैं कि उदाहरण के लिए उच्च मात्रा में मौजूद एक्सेप्शन स्टैकट्रैक लॉग में डंप नहीं हैं?
अन्य संख्याएँ कभी-कभी अधिक होती हैं, इसलिए हो सकता है कि स्लोडाउन अपवाद लॉगिंग से संबंधित हो? या यहां तक ​​कि स्वैपिंग, अगर रैम कम हो जाता है?
वास्तव में मैं सोच रहा हूं, अगर कोई एप्लिकेशन लॉग में कुछ भी नहीं लिखता है, यह समस्याओं के बिना चिकनी चलने का संकेत है (जब तक कि यह इस समय पूरी तरह से जमे हुए नहीं है)। 12-22 सेकंड से क्या हो रहा है (यहाँ OpenJDK14 मामले में) मुझे और क्या चिंता होगी ... लॉग इन पंक्तियाँ छत से गुजरती हैं ... क्यों ?
और बाद में प्रवेश 1-2k के बारे में लाइनों की हमेशा की तरह कम मूल्यों के लिए नीचे चला जाता है ... के लिए क्या कारण है कि ?? (ठीक है, शायद यह 22 सेकंड में जीसी किकिंग है और क्या तबला रस है जो कुछ चीजों को हल करता है ...?)

एक और बात "सिंगल सीपीयू" मशीनों के बारे में आपका कथन हो सकता है। क्या इसका अर्थ "सिंगल कोर" भी है (Idk, हो सकता है कि आपका सॉफ़्टवेयर विरासत हार्डवेयर या कुछ और पर आधारित हो)? और "सिंगल सीपीयू" वीएम उन मशीनों पर चल रहे हैं? लेकिन मुझे लगता है, मैं इन धारणाओं के बारे में गलत हूं, क्योंकि आजकल लगभग सभी सीपीयू मल्टीकोर हैं ... लेकिन मैं शायद एक मल्टीथ्रेडिंग मुद्दे (गतिरोध) समस्या पर जांच करूंगा।


2
कृपया अपने पोस्ट में हस्ताक्षर या टैगलाइन का उपयोग न करें, यहां दोहराए गए "जीएल और एचएफ" को शोर और आपके पोस्ट की सामग्री से एक व्याकुलता माना जाता है। अधिक जानकारी के लिए meta.stackexchange.com/help/behavior देखें ।
meagar

1
"क्या मैं सही ढंग से समझता हूं कि आपका एप्लिकेशन रनिंग के पहले सेकंड (ओपनजेडकेके) के भीतर लॉग करने के लिए लगभग 30710 लाइनें लिखता है?" - हाँ तुम सही हो।
पालक

1
"क्या आपको यकीन है कि लॉग में डंप किए गए अपवाद स्टैक्ट्रेक्ट्स की उच्च मात्रा उदाहरण के लिए नहीं हैं?" - लॉग साफ है, मुझे वहां कुछ भी अजीब नहीं मिला है, एप्लिकेशन सही तरीके से काम करता है (सिवाय इसके कि यह बहुत धीरे-धीरे चलता है)।
पालक

1
जीसी 22 वें सेकंड में किक कर रहा है और इसके बाद ऐप धीमा रहता है। मैंने भी सवाल अपडेट किया है। कृपया ध्यान दें कि अपडेट 4j डेमो ऐप में भी यही समस्या है। जवाब के लिए धन्यवाद!
19

1
एक सेकंड में 30k + लॉग लाइनें काफी विशाल हैं ... क्या आप सहमत नहीं हैं? मुझे वास्तव में आश्चर्य है कि इतने कम समय में लॉग लाइनों की इस उच्च राशि को स्वीकार करने के लिए लॉग इन करने के लिए क्या उपयोगी हो सकता है ... क्या आपने लॉगिंग पूरी तरह से बंद करने की कोशिश की और इस मोड में एप्लिकेशन को प्रोफाइल किया? (मैं उत्सुक हूँ, लेकिन शायद प्रवेश करने के रूप में आप update4j व्यवहार के साथ मतलब वास्तव में कोई प्रभाव नहीं पड़ता)
Antares

5

चूंकि यह 100% CPU "अधिकांश समय" का उपयोग कर रहा है, और जावा 14 के साथ इसे 10 गुना अधिक (!) लगता है, इसका मतलब है कि आप अपने CPU का 90% जावा 14 में बर्बाद कर रहे हैं।

ढेर में स्थान कम कर सकते हैं कि करते हैं, के रूप में आप जी सी में समय की एक पूरी बहुत खर्च करते हैं, लेकिन आप उस की संभावना से इनकार किया है लगते हैं।

मुझे लगता है कि आप पक्षपाती लॉकिंग विकल्प को घुमा रहे हैं, और यह एक महत्वपूर्ण अंतर बनाता है। यह मुझे बताता है कि शायद आपका प्रोग्राम कई थ्रेड्स में बहुत समवर्ती कार्य करता है। यह संभव है कि आपके कार्यक्रम में एक संक्षिप्त नाम बग है जो जावा 14 में दिखाई देता है, लेकिन जावा 10 में नहीं। यह भी बता सकता है कि क्यों एक और सीपीयू जोड़ने से यह दो बार से अधिक तेज हो जाता है।

जब आप अशुभ होते हैं, तब कंज्यूरी बग अक्सर ही दिखाई देते हैं, और ट्रिगर वास्तव में कुछ भी हो सकता है, जैसे हैशमैप संगठन में बदलाव आदि।

सबसे पहले, अगर यह संभव है, तो किसी भी छोरों की जांच करें जो सोने के बजाय व्यस्त-प्रतीक्षा कर सकते हैं।

फिर, नमूना मोड में एक प्रोफाइलर चलाएं (jvisualvm करेंगे) और उन तरीकों की तलाश करें जो कुल समय का बहुत बड़ा% ले रहे हैं जितना उन्हें चाहिए। चूँकि आपका प्रदर्शन 10 के एक कारक से बंद है, इसलिए वहाँ की कोई भी समस्या वास्तव में समाप्त हो जानी चाहिए।


अतीत में बायस्ड लॉकिंग आवश्यक थी, लेकिन आजकल इतना नहीं है, और इसे डिफ़ॉल्ट रूप से अक्षम करने का प्रस्ताव है और बाद में हटा दिया गया है: openjdk.java.net/jeps/374
जोहान्सबी

2

यह एक दिलचस्प मुद्दा है और इसे कम करने के लिए अनिश्चित मात्रा में प्रयास की आवश्यकता होगी क्योंकि कई क्रमपरिवर्तन और संयोजन हैं जिन्हें आजमाया जाना चाहिए और एकत्र किए गए और एकत्र किए गए डेटा की आवश्यकता होगी।

ऐसा लगता है कि कुछ समय के लिए इसका कोई संकल्प नहीं किया गया है। शायद इसे आगे बढ़ाने की आवश्यकता हो सकती है।

EDIT 2: चूंकि "थ्रेडलोकलेंडशेक" को हटा दिया गया है और हम यह मान सकते हैं कि लॉकिंग का बचाव किया गया है, इस परिदृश्य को गति देने के लिए "UseBiasedLocking" के बिना प्रयास करें।

हालाँकि अधिक डेटा एकत्र करने और समस्या को अलग करने का प्रयास करने के लिए कुछ सुझाव हैं।

  1. एक से अधिक कोर आवंटित करें [मैं देखता हूं कि आपने इसे आज़मा लिया है और समस्या दूर हो जाती है। लगता है कि थ्रेड / एस निष्पादन के साथ एक मुद्दा हो सकता है दूसरों को छोड़कर। नीचे कोई 7 देखें)
  2. अधिक ढेर आवंटित करें (शायद v14 की मांग पहले के jdks से अधिक है)
  3. विन 10 वीबी को अधिक मेमोरी आवंटित करें।
  4. OS सिस्टम संदेशों की जांच करें (आपके मामले में 10 जीतें)
  5. इसे नॉन-वर्चुअलाइज्ड विन 10 में चलाएं।
  6. Jdk 14 के एक अलग बिल्ड का प्रयास करें
  7. प्रत्येक थ्रेड डंप करें (या प्रोफ़ाइल) समय के कुछ अंतराल। विश्लेषण करें कि क्या धागा विशेष रूप से चल रहा है। शायद समान समय साझा करने के लिए एक सेटिंग है। शायद वहाँ एक उच्च प्राथमिकता धागा चल रहा है। वह धागा क्या है और यह क्या कर रहा है? लिनक्स में आप एक प्रक्रिया और वास्तविक समय में इसकी स्थिति से जुड़ी हल्की प्रक्रियाओं (थ्रेड्स) को स्टेट कर सकते हैं। विन 10 पर कुछ ऐसा ही?
  8. सि पि यु का उपयोग? 100% या उससे कम? सीपीयू या मेम द्वारा विवश? सेवा धागे में 100% CPU? कौन सा सेवा धागा?
  9. क्या आपने स्पष्ट रूप से GC algo सेट किया है?

मैंने व्यक्तिगत रूप से उन संस्करणों के मुद्दों को देखा है जिन्हें जीसी, हीप रिसाइजिंग, वर्चुअलाइज्ड कंटेनरों के साथ और इसी तरह से करना है।

इसका कोई आसान जवाब नहीं है, मुझे लगता है, खासकर जब से यह सवाल कुछ समय के लिए रहा है। लेकिन हम कोशिश कर सकते हैं, सभी सर्वश्रेष्ठ और हमें बताएं कि इन अलगाव चरणों में से कुछ का परिणाम क्या है।

EDIT 1: अद्यतन किए गए प्रश्न से, यह एक जीसी या किसी अन्य सेवा थ्रेड को एकल कोर गैर-समरूप (थ्रेड-लोकल हैंडशेक) से अधिक लगता है?


एक अतिरिक्त CPU कोर को जोड़ने के लिए उपयोग किया जाता है जो कि जावा एर्गोनॉमिक्स से 32 बिट सिस्टम पर क्लाइंट से सर्वर क्लास vm के लिए अलग GC और Tiered संकलन के साथ होता है, अगर ऐसा अभी भी हो तो यह प्रदर्शन और मेमोरी के उपयोग में अचानक अंतर बता सकता है, हाँ JVM प्रदर्शन जटिल है is
जोहान्सबी

3
जावा एर्गोनॉमिक्स (डिफ़ॉल्ट सेटिंग्स) अभी भी 1 सीपीयू के लिए अलग हैं (जैसे: -XX: + UseSerialGC) या 2 सीपीयू (जैसे: G1GC, LoopStripMiningIter = 1000, ... ShortLoop = 100) लेकिन -XX के साथ सुनिश्चित करने के बाद: + PrintFlagsFinal कि मैंने सभी मापदंडों को समान या समान रनिंग अपडेट 4j के लिए टाल दिया, फिर भी 2 CPU के बजाय cmd.exe / C start / affinity 0x1 के साथ केवल एक के साथ शुरू करने के लिए बेहद धीमा था (लेकिन 0x3 के साथ अत्यंत तेज़ - इस प्रकार 2 cpus (1 +) का उपयोग करना 10 बाइनरी))। मैंने पुष्टि की कि हम एप्सिलॉन जीसी का उपयोग करके किसी भी कचरा कलेक्टर को दोष नहीं दे सकते हैं जो कि किसी भी जीसी ओवरहेड से बचने के लिए डिज़ाइन किया गया है। हालांकि TieredCompilation सक्षम है
जोहान्सबी

समझा। एप्सिलॉन जीसी के साथ, ऐसा लगता है जैसे यह धीमा था। इस स्थिति में, थ्रेड स्टेटस और डंप का मूल्यांकन करने के लिए कि यह कहाँ अटक जाता है एक तरीका हो सकता है। जावा की दुनिया और ओएस की दुनिया में दोनों (linux अगर मुझे याद है कि गोरखधंधा था)
खन्ना111

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 पर काम नहीं करता है।)

VirtualBox में विंडोज 10 x64 पर कुछ माप (दो सीपीयू के साथ):

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 एमएस।

मैंने इस निष्कर्ष को हॉटस्पॉट-देव @ ओपनज्डक मेल सूची में भेजा है और देवों ने पुष्टि की है कि यह कुछ ऐसा है जिसे जेडीके बेहतर तरीके से संभाल सकता है । आप थ्रेड में माना गया फ़िक्स भी पा सकते हैं । उम्मीद है कि इसे OpenJDK 15 में तय किया जाएगा।


प्रतिक्रिया के लिए धन्यवाद!
Antares

1

धीमे डिस्क में प्रवेश करने से सावधान रहें, यह आपके एप्लिकेशन को धीमा कर देगा:

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

लेकिन यह समस्या का कारण बनने की संभावना नहीं है क्योंकि सीपीयू अभी भी व्यस्त है और आपको थ्रेड-लोकल हैंडशेक: https: // openjdk की बदौलत सभी बिंदुओं के सुरक्षित स्थान पर आने की प्रतीक्षा करने की जरूरत नहीं है । java.net/jeps/312

सीधे तौर पर आपके पास समस्या से संबंधित नहीं है, लेकिन आम तौर पर यदि आप स्टार्टअप समय के लिए अपने हार्डवेयर से अधिक प्रदर्शन को निचोड़ने का प्रयास करना चाहते हैं, तो AppCDS (वर्ग डेटा साझाकरण) पर एक नज़र डालें:

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.