2012-12-18 9 views
12

संभव डुप्लिकेट:
What makes JNI calls slow?ओवरहेड फोन

सबसे पहले मुझे कहना है कि इस सवाल वास्तविक आवश्यकता की तुलना में जिज्ञासा से बाहर अधिक पैदा होता है करते हैं।

मुझे यह जानकर उत्सुकता है कि जावा से जेएनआई कॉल करने में ओवरहेड क्या है, कहें, System.arraycopy सरणी आवंटित करने और तत्वों को लूप के साथ कॉपी करने के विरुद्ध।

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

मुझे मेरे सवाल का स्पष्ट करते हैं:

मुझे पता है कि arraycopy का उपयोग कर जावा में एक सरणी कॉपी करने के लिए सबसे तेज़ तरीका है।

कहा जा रहा है, मान लीजिए कि मैं इसका उपयोग केवल एक तत्व की सरणी की प्रतिलिपि बनाने के लिए कर रहा हूं। चूंकि मैं अंतर्निहित ओएस को ऐसा करने के लिए बुला रहा हूं, इसलिए में इस कॉल में ओवरहेड होने के लिए है। मुझे यह जानने में दिलचस्पी है कि यह ओवरहेड क्या है और कॉल की प्रक्रिया में क्या होता है।

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

+1

आपको याद है, 'सिस्टम' कॉल कुछ हद तक भ्रमित शब्द है क्योंकि इसे [सिस्टम कॉल] (https://en.wikipedia.org/wiki/System_call) के लिए गलत माना जा सकता है। –

+0

वैसे, http://stackoverflow.com/questions/2772152/why-is-system-arraycopy-native-in-java – NPE

+2

में जानकारी का भरपूर धन है मेरा जवाब हटा दिया गया, मुझे लगता है कि यह आपकी मदद करेगा: http: //stackoverflow.com/questions/7699020/what-makes-jni-calls-slow –

उत्तर

9

जब से मैं ऐसा करने के लिए अंतर्निहित ओएस फोन कर रहा हूँ ...

आप system calls काफी महंगे हैं सही है कि कर रहे हैं।हालांकि, SystemSystem.arraycopy() में एक गलत नामक है। इसमें कोई सिस्टम कॉल शामिल नहीं है।

... इस कॉल में एक ओवरहेड होना चाहिए। मुझे यह जानने में दिलचस्पी है कि यह ओवरहेड क्या है और कॉल की प्रक्रिया में क्या होता है।

जब आप System.arraycopy() की परिभाषा को देखो, यह native रूप में घोषित किया है। इसका मतलब है कि विधि सी ++ में लागू की गई है। यदि आप इतने इच्छुक थे, तो आप जेडीके स्रोत कोड देख सकते हैं, और सी ++ फ़ंक्शन ढूंढ सकते हैं। ओपनजेडीके 7 में, इसे JVM_ArrayCopy() कहा जाता है और hotspot/src/share/vm/prims/jvm.cpp में रहता है। कार्यान्वयन आश्चर्यजनक रूप से जटिल है, लेकिन यह गहराई से यह memcpy() है।

यदि arraycopy() सामान्य देशी फ़ंक्शन के रूप में उपयोग किया जा रहा है, तो इसे कॉल करने के लिए ओवरहेड है। तर्क जांच आदि के कारण और ओवरहेड है

हालांकि, यह बहुत संभावना है कि JIT compilerSystem.arraycopy() के बारे में जानता है। इसका मतलब है कि, C++ फ़ंक्शन को कॉल करने के बजाय, कंपाइलर जानता है कि सरणी प्रतिलिपि बनाने के लिए विशेष रूप से तैयार किए गए मशीन कोड को कैसे उत्पन्न किया जाए। मुझे अन्य जेवीएम के बारे में पता नहीं है, लेकिन हॉटस्पॉट में System.arraycopy() के लिए ऐसा "आंतरिक" समर्थन है।

चलो कहते हैं कि मैं इसे उपयोग कर रहा हूँ केवल एक ही तत्व

यदि आपका सरणी छोटे है की एक सरणी कॉपी करने के लिए करते हैं, तो आप एक हाथ से तैयार किए पाश के साथ System.arraycopy() को हराने में सक्षम हो सकता है। यदि आकार संकलन समय पर ज्ञात है, तो आप शायद बेहतर भी कर सकते हैं, तब से आप लूप को अनलॉक भी कर सकते हैं। हालांकि, यह सब परिस्थितियों को कम करने के अलावा वास्तव में प्रासंगिक नहीं है।

+0

+1 मूल कॉल को रेखांकित करने का बिंदु सबसे महत्वपूर्ण योगदान है। –

+0

आपका उत्तर, साथ ही टिप्पणी जिसने मुझे इसकी ओर इशारा किया: http://stackoverflow.com/questions/7699020/what-makes-jni-calls-slow सबसे सहायक रहा है, इसलिए मैं स्वीकार कर रहा हूं। कुछ शब्दावली को साफ़ करने के लिए धन्यवाद जो मैंने नहीं किया ' टी बहुत स्पष्ट रूप से बाहर रखा गया है। – pcalcao

+1

+1 किसी भी प्रश्न के लिए मैंने देखा है सबसे अच्छे उत्तरों में से एक – Bohemian

0

आपके पास यह गलत तरीका है। System.arraycopy() का सबसे तेज़ देशी JVM

द्वारा प्रदान की कार्यान्वयन कोई "भूमि के ऊपर" है - वहाँ केवल "लाभ" है

2

java.util.Arrays.copyOf कार्यान्वयन, जैसे पर एक नजर डालें

public static byte[] copyOf(byte[] original, int newLength) { 
    byte[] copy = new byte[newLength]; 
    System.arraycopy(original, 0, copy, 0, 
        Math.min(original.length, newLength)); 
    return copy; 
} 

वे System.arraycopy का उपयोग करते हैं क्योंकि यह सबसे तेज़ तरीका है।

तुम्हारा मतलब हैं कि Java में देशी तरीकों बुला महंगा है तो कम से http://www.javamex.com/tutorials/jni/overhead.shtml

अद्यतन एक बार देख ले प्रश्न वाकई दिलचस्प है, इसलिए मैं कुछ परीक्षण किया है

 long t0 = System.currentTimeMillis(); 
     byte[] a = new byte[100]; 
     byte[] b = new byte[100]; 
     for(int i = 0; i < 10000000; i++) { 
//   for(int j = 0; j < a.length; j++) { 
//    a[j] = b[j]; 
//   } 
      System.arraycopy(b, 0, a, 0, a.length); 
     } 
     System.out.println(System.currentTimeMillis() - t0); 

ऐसा नहीं है कि पता चलता है बहुत कम सरणी पर (< 10) System.arraycopy भी धीमा हो सकता है, संभवतः क्योंकि यह मूल है, लेकिन बड़े सरणी पर इससे कोई फर्क नहीं पड़ता, System.arraycopy बहुत तेज़ है।

+0

धन्यवाद, लिंक के लिए ऊपर उठाया गया, जो वास्तव में मैं खोज रहा था। – pcalcao

+0

मैंने कुछ परीक्षण जोड़े हैं, मेरा अपडेट –

+0

* "देखें ...सबसे अधिक संभावना है क्योंकि यह मूल है "* - अन्य संभावित स्पष्टीकरण हैं, उदाहरण के लिए पुस्तक को देखते हुए कि 'arraycopy()' को तर्कों की जांच करने के लिए करना है, और प्रतिलिपि करने का सही तरीका चुनें। –

1

मुझे जेएनआई कॉल के ओवरहेड को जानने में दिलचस्पी है, और वास्तविक कॉल में क्या शामिल है।

System.arraycopy() विधि बल्कि जटिल * है और यह संभावना नहीं है कि JIT कम्पाइलर inlines यह (अन्य उत्तर में से एक से पता चलता है के रूप में)।

दूसरी तरफ, यह संभावना है कि जेआईटी कंपाइलर एक अनुकूलित कॉलिंग अनुक्रम का उपयोग करता है, क्योंकि यह एक आंतरिक मूल विधि है। दूसरे शब्दों में, यह संभवतः एक सामान्य जेएनआई कॉल नहीं है।


* - System.arraycopy एक सरल स्मृति प्रतिलिपि नहीं है। इसे सरणी सीमाओं से परे पढ़ने या लिखने से बचने के लिए अपने तर्कों का परीक्षण करना है, और इसी तरह। और इस मामले में जब आप एक ऑब्जेक्ट सरणी से दूसरी ओर कॉपी कर रहे हैं तो कॉपी की गई प्रत्येक ऑब्जेक्ट की वास्तविक प्रकार को जांचने की आवश्यकता है। यह सब इनलाइन के लिए समझदार होने की तुलना में कहीं अधिक कोड तक जोड़ता है।

संबंधित मुद्दे