X64 जावा में int की तुलना में लंबा क्यों है?


90

मैं एक सर्फेस प्रो 2 टैबलेट पर जावा 7 अपडेट 45 x64 (कोई 32 बिट जावा स्थापित) के साथ विंडोज 8.1 x64 चला रहा हूं।

नीचे का कोड 1688ms लेता है जब i का प्रकार एक लंबा और 109ms होता है जब मैं एक इंट होता है। 64 बिट JVM के साथ 64 बिट प्लेटफ़ॉर्म पर इंट की तुलना में लॉन्ग (64 बिट प्रकार) का परिमाण धीमा क्यों है?

मेरा एकमात्र अनुमान यह है कि सीपीयू 32 बिट की तुलना में 64 बिट पूर्णांक जोड़ने में अधिक समय लेता है, लेकिन ऐसा लगता है कि संभावना नहीं है। मुझे संदेह है कि हसवेल रिपल-कैरी योजक का उपयोग नहीं करता है।

मैं इसे ग्रहण केपलर SR1, btw में चला रहा हूं।

public class Main {

    private static long i = Integer.MAX_VALUE;

    public static void main(String[] args) {    
        System.out.println("Starting the loop");
        long startTime = System.currentTimeMillis();
        while(!decrementAndCheck()){
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Finished the loop in " + (endTime - startTime) + "ms");
    }

    private static boolean decrementAndCheck() {
        return --i < 0;
    }

}

संपादित करें: यहां वीएस 2013 (नीचे), समान प्रणाली द्वारा संकलित समकक्ष सी ++ कोड के परिणाम हैं। लंबा: 72265ms int: 74656ms वे परिणाम डीबग 32 बिट मोड में थे।

64 बिट रिलीज़ मोड में: लंबा: 875 मी लंबा लंबा: 906ms int: 1047ms

इससे पता चलता है कि मैंने जो परिणाम देखा, वह सीपीयू सीमाओं के बजाय जेवीएम ऑप्टिमाइज़ेशन अजीबता है।

#include "stdafx.h"
#include "iostream"
#include "windows.h"
#include "limits.h"

long long i = INT_MAX;

using namespace std;


boolean decrementAndCheck() {
return --i < 0;
}


int _tmain(int argc, _TCHAR* argv[])
{


cout << "Starting the loop" << endl;

unsigned long startTime = GetTickCount64();
while (!decrementAndCheck()){
}
unsigned long endTime = GetTickCount64();

cout << "Finished the loop in " << (endTime - startTime) << "ms" << endl;



}

संपादित करें: जावा 8 आरटीएम में बस फिर से यह कोशिश की, कोई महत्वपूर्ण बदलाव नहीं।


8
सबसे अधिक संभावना संदिग्ध है कि आपका सेट अप सीपीयू या जेवीएम के विभिन्न भागों का नहीं है। क्या आप मज़बूती से इस माप को पुन: उत्पन्न कर सकते हैं? लूप को दोहराना नहीं, जेआईटी को वार्मिंग नहीं करना currentTimeMillis(), कोड का उपयोग करना , रनिंग कोड जो तुच्छ रूप से पूरी तरह से अनुकूलित किया जा सकता है, आदि अविश्वसनीय परिणाम का पुन: उपयोग करता है।

1
मैं थोड़ी देर पहले बेंचमार्किंग कर रहा था, मुझे longलूप काउंटर के रूप में उपयोग करना था , क्योंकि जेआईटी कंपाइलर ने लूप को अनुकूलित किया था, जब मैंने ए का उपयोग किया था int। किसी को जनरेट किए गए मशीन कोड की गड़बड़ी को देखना होगा।
सैम

7
यह एक सही माइक्रोबैनमार्क नहीं है, और मुझे उम्मीद नहीं होगी कि इसके परिणाम किसी भी तरह से वास्तविकता को दर्शाते हैं।
लुई वासरमैन

7
एक उचित जावा microbenchmark लिखने में नाकाम रहने के लिए ओपी को बर्खास्त करने वाली सभी टिप्पणियाँ बहुत ही आलसी हैं। यह उस तरह की बात है जो यह पता लगाने के लिए बहुत आसान है कि आप बस देखते हैं और देखते हैं कि जेवीएम कोड को क्या करता है।
20

2
@maaartinus: स्वीकृत अभ्यास को स्वीकार अभ्यास है क्योंकि यह ज्ञात नुकसान की सूची के आसपास काम करता है। उचित जावा बेंचमार्क के मामले में, आप यह सुनिश्चित करना चाहते हैं कि आप ठीक से अनुकूलित कोड को माप रहे हैं, ऑन-स्टैक रिप्लेसमेंट नहीं, और आप यह सुनिश्चित करना चाहते हैं कि आपके माप अंत में साफ हों। ओपी को एक पूरी तरह से अलग मुद्दा मिला और उन्होंने जो बेंचमार्क प्रदान किया वह पर्याप्त रूप से प्रदर्शित किया। और, जैसा कि कहा गया है, इस कोड को एक उचित जावा बेंचमार्क में बदलना वास्तव में अजीबता को दूर नहीं करता है। और विधानसभा कोड पढ़ना मुश्किल नहीं है।
tmyklebu

जवाबों:


80

जब आप उपयोग करते हैं तो मेरा JVM इनर लूप में यह बहुत सीधी बात करता है long:

0x00007fdd859dbb80: test   %eax,0x5f7847a(%rip)  /* fun JVM hack */
0x00007fdd859dbb86: dec    %r11                  /* i-- */
0x00007fdd859dbb89: mov    %r11,0x258(%r10)      /* store i to memory */
0x00007fdd859dbb90: test   %r11,%r11             /* unnecessary test */
0x00007fdd859dbb93: jge    0x00007fdd859dbb80    /* go back to the loop top */

यह धोखा देता है, कठिन, जब आप intएस का उपयोग करते हैं ; पहले कुछ पेंच हैं जिन्हें मैं समझने का दावा नहीं करता लेकिन एक अनियंत्रित लूप के लिए सेटअप जैसा दिखता है:

0x00007f3dc290b5a1: mov    %r11d,%r9d
0x00007f3dc290b5a4: dec    %r9d
0x00007f3dc290b5a7: mov    %r9d,0x258(%r10)
0x00007f3dc290b5ae: test   %r9d,%r9d
0x00007f3dc290b5b1: jl     0x00007f3dc290b662
0x00007f3dc290b5b7: add    $0xfffffffffffffffe,%r11d
0x00007f3dc290b5bb: mov    %r9d,%ecx
0x00007f3dc290b5be: dec    %ecx              
0x00007f3dc290b5c0: mov    %ecx,0x258(%r10)   
0x00007f3dc290b5c7: cmp    %r11d,%ecx
0x00007f3dc290b5ca: jle    0x00007f3dc290b5d1
0x00007f3dc290b5cc: mov    %ecx,%r9d
0x00007f3dc290b5cf: jmp    0x00007f3dc290b5bb
0x00007f3dc290b5d1: and    $0xfffffffffffffffe,%r9d
0x00007f3dc290b5d5: mov    %r9d,%r8d
0x00007f3dc290b5d8: neg    %r8d
0x00007f3dc290b5db: sar    $0x1f,%r8d
0x00007f3dc290b5df: shr    $0x1f,%r8d
0x00007f3dc290b5e3: sub    %r9d,%r8d
0x00007f3dc290b5e6: sar    %r8d
0x00007f3dc290b5e9: neg    %r8d
0x00007f3dc290b5ec: and    $0xfffffffffffffffe,%r8d
0x00007f3dc290b5f0: shl    %r8d
0x00007f3dc290b5f3: mov    %r8d,%r11d
0x00007f3dc290b5f6: neg    %r11d
0x00007f3dc290b5f9: sar    $0x1f,%r11d
0x00007f3dc290b5fd: shr    $0x1e,%r11d
0x00007f3dc290b601: sub    %r8d,%r11d
0x00007f3dc290b604: sar    $0x2,%r11d
0x00007f3dc290b608: neg    %r11d
0x00007f3dc290b60b: and    $0xfffffffffffffffe,%r11d
0x00007f3dc290b60f: shl    $0x2,%r11d
0x00007f3dc290b613: mov    %r11d,%r9d
0x00007f3dc290b616: neg    %r9d
0x00007f3dc290b619: sar    $0x1f,%r9d
0x00007f3dc290b61d: shr    $0x1d,%r9d
0x00007f3dc290b621: sub    %r11d,%r9d
0x00007f3dc290b624: sar    $0x3,%r9d
0x00007f3dc290b628: neg    %r9d
0x00007f3dc290b62b: and    $0xfffffffffffffffe,%r9d
0x00007f3dc290b62f: shl    $0x3,%r9d
0x00007f3dc290b633: mov    %ecx,%r11d
0x00007f3dc290b636: sub    %r9d,%r11d
0x00007f3dc290b639: cmp    %r11d,%ecx
0x00007f3dc290b63c: jle    0x00007f3dc290b64f
0x00007f3dc290b63e: xchg   %ax,%ax /* OK, fine; I know what a nop looks like */

फिर स्वयं अनियंत्रित लूप:

0x00007f3dc290b640: add    $0xfffffffffffffff0,%ecx
0x00007f3dc290b643: mov    %ecx,0x258(%r10)
0x00007f3dc290b64a: cmp    %r11d,%ecx
0x00007f3dc290b64d: jg     0x00007f3dc290b640

फिर अनियंत्रित लूप के लिए फाड़ कोड, अपने आप में एक परीक्षण और एक सीधा लूप:

0x00007f3dc290b64f: cmp    $0xffffffffffffffff,%ecx
0x00007f3dc290b652: jle    0x00007f3dc290b662
0x00007f3dc290b654: dec    %ecx
0x00007f3dc290b656: mov    %ecx,0x258(%r10)
0x00007f3dc290b65d: cmp    $0xffffffffffffffff,%ecx
0x00007f3dc290b660: jg     0x00007f3dc290b654

इसलिए यह 16 गुना तेज गति से अंदर जाता है क्योंकि JIT ने intलूप को 16 बार अनियंत्रित किया है, लेकिन longलूप को बिल्कुल भी अनियंत्रित नहीं किया है ।

पूर्णता के लिए, यहां वह कोड है जिसे मैंने वास्तव में आज़माया था:

public class foo136 {
  private static int i = Integer.MAX_VALUE;
  public static void main(String[] args) {
    System.out.println("Starting the loop");
    for (int foo = 0; foo < 100; foo++)
      doit();
  }

  static void doit() {
    i = Integer.MAX_VALUE;
    long startTime = System.currentTimeMillis();
    while(!decrementAndCheck()){
    }
    long endTime = System.currentTimeMillis();
    System.out.println("Finished the loop in " + (endTime - startTime) + "ms");
  }

  private static boolean decrementAndCheck() {
    return --i < 0;
  }
}

विकल्पों का उपयोग करके विधानसभा डंप उत्पन्न किए गए थे -XX:+UnlockDiagnosticVMOptions -XX:+PrintAssembly। ध्यान दें कि आपको यह काम करने के लिए अपने जेवीएम इंस्टॉलेशन के साथ गड़बड़ करना होगा; आपको बिल्कुल सही जगह पर कुछ यादृच्छिक साझा पुस्तकालय डालने की आवश्यकता है या यह विफल हो जाएगा।


8
ठीक है, इसलिए नेट-नेट यह नहीं है कि longसंस्करण धीमा है, बल्कि intसंस्करण की तुलना में तेज है। यह समझ आता है। संभवत: जेआईटी के अनुकूलन के longभाव बनाने में उतने प्रयास का निवेश नहीं किया गया ।
हॉट लिक्स

1
... मेरी अज्ञानता को क्षमा करें, लेकिन "वित्त पोषित" क्या है? मैं शब्द को ठीक से देख भी नहीं सकता, और यह पहली बार है जब मैंने किसी से पूछा है कि इंटरनेट पर किसी शब्द का क्या अर्थ है।
ब्रायन एचएच

1
@BrianDHall "ध्वज" के लिए कमांड-लाइन स्विच के रूप में gccउपयोग करता है -f, और unroll-loopsअनुकूलन को कहकर चालू किया जाता है -funroll-loops। मैं अनुकूलन का वर्णन करने के लिए बस "अनियंत्रित" का उपयोग करता हूं।
चिर्लिस -कुट्योपोटेमिमिस्टिक-

4
@BRPocock: जावा कंपाइलर नहीं कर सकता, लेकिन JIT सुनिश्चित कर सकता है।
tmyklebu

1
बस स्पष्ट होने के लिए, यह "" वित्त पोषण "नहीं किया था। इसने इसे अनियंत्रित कर दिया और अनियंत्रित लूप को परिवर्तित कर दिया i-=16, जो निश्चित रूप से 16x तेज है।
अलेक्सांद्र डबिन्स्की

22

JVM ढेर के संदर्भ में परिभाषित किया गया है शब्द , जिसका आकार एक कार्यान्वयन विस्तार है, लेकिन कम से कम 32 बिट चौड़ी होनी चाहिए। जेवीएम कार्यान्वयनकर्ता 64-बिट शब्दों का उपयोग कर सकता है , लेकिन बायटेकोड इस पर भरोसा नहीं कर सकता है, और इसलिए longया doubleमूल्यों के साथ संचालन को अतिरिक्त देखभाल के साथ संभालना होगा। विशेष रूप से, JVM पूर्णांक शाखा निर्देशों को ठीक प्रकार पर परिभाषित किया गया है int

आपके कोड के मामले में, disassembly शिक्षाप्रद है। intओरेकल जेडडीके 7 द्वारा संकलित संस्करण के लिए यहां बायटेकोड है :

private static boolean decrementAndCheck();
  Code:
     0: getstatic     #14  // Field i:I
     3: iconst_1      
     4: isub          
     5: dup           
     6: putstatic     #14  // Field i:I
     9: ifge          16
    12: iconst_1      
    13: goto          17
    16: iconst_0      
    17: ireturn       

ध्यान दें कि जेवीएम आपके स्थिर i(0) के मूल्य को लोड करेगा , एक (3-4) को घटाएगा, स्टैक (5) पर मूल्य की नकल करेगा, और इसे चर (6) में वापस धकेल देगा। यह एक तुलना-शून्य शाखा और रिटर्न के साथ करता है।

संस्करण longथोड़ा और अधिक जटिल है:

private static boolean decrementAndCheck();
  Code:
     0: getstatic     #14  // Field i:J
     3: lconst_1      
     4: lsub          
     5: dup2          
     6: putstatic     #14  // Field i:J
     9: lconst_0      
    10: lcmp          
    11: ifge          18
    14: iconst_1      
    15: goto          19
    18: iconst_0      
    19: ireturn       

सबसे पहले, जब JVM स्टैक (5) पर नए मूल्य को दोहराता है, तो उसे दो स्टैक शब्दों को डुप्लिकेट करना होगा। आपके मामले में, यह काफी संभव है कि यह किसी को डुप्लिकेट करने से अधिक महंगा नहीं है, क्योंकि जेवीएम सुविधाजनक होने पर 64-बिट शब्द का उपयोग करने के लिए स्वतंत्र है। हालाँकि, आप देखेंगे कि शाखा तर्क यहाँ लंबा है। जेवीएम में longशून्य के साथ तुलना करने का निर्देश नहीं है , इसलिए इसे 0Lस्टैक (9) पर एक स्थिर धक्का देना पड़ता है , एक सामान्य longतुलना (10) करते हैं, और फिर उस गणना के मूल्य पर शाखा करते हैं ।

यहाँ दो प्रशंसनीय परिदृश्य हैं:

  • JVM बिल्कुल बाईटेकोड पथ का अनुसरण कर रहा है। इस मामले में, यह longकई अतिरिक्त मूल्यों को धकेलने और पॉप करने के संस्करण में अधिक काम कर रहा है , और ये वर्चुअल प्रबंधित स्टैक पर हैं , न कि वास्तविक हार्डवेयर-समर्थित सीपीयू स्टैक। यदि यह मामला है, तो आपको वार्मअप के बाद भी महत्वपूर्ण प्रदर्शन अंतर दिखाई देगा।
  • JVM को पता चलता है कि वह इस कोड को ऑप्टिमाइज़ कर सकता है। इस मामले में, व्यावहारिक रूप से अनावश्यक धक्का / तर्क की तुलना करने में से कुछ को अनुकूलित करने के लिए अतिरिक्त समय लग रहा है। यदि यह मामला है, तो आपको वार्मअप के बाद बहुत कम प्रदर्शन अंतर दिखाई देगा।

मैं आपको JIT किक में होने के प्रभाव को खत्म करने के लिए एक सही माइक्रोबैनमार्क लिखने की सलाह देता हूं , और यह भी एक अंतिम शर्त के साथ यह कोशिश कर रहा हूं कि शून्य नहीं है, जेवीएम को intउस पर तुलना करने के लिए मजबूर करने के लिए जो इसके साथ करता है long


1
@ कटोना जरूरी नहीं। विशेष रूप से, क्लाइंट और सर्वर हॉटस्पॉट JVM पूरी तरह से अलग कार्यान्वयन हैं, और इल्या ने सर्वर का चयन करने का संकेत नहीं दिया (क्लाइंट आमतौर पर 32-बिट डिफ़ॉल्ट है)।
चिर्लिस -कुट्योपोटेमिमिस्टिक-

1
@tmyklebu मुद्दा यह है कि बेंचमार्क एक साथ कई अलग-अलग चीजों को माप रहा है। नॉनजेरो टर्मिनल स्थिति का उपयोग करने से चरों की संख्या कम हो जाती है।
चिर्लिस -कुट्योपोटेमिमिस्टिक-

1
@tmyklebu बिंदु यह है कि ओपी का इरादा इन्टर्स बनाम लॉन्ग्स पर वेतन वृद्धि, वेतन वृद्धि और तुलनाओं की तुलना करना था। इसके बजाय (यह उत्तर सही है) वे केवल तुलना कर रहे थे, और केवल 0 के खिलाफ, जो एक विशेष मामला है। यदि और कुछ नहीं है, तो यह मूल बेंचमार्क को भ्रामक बनाता है - ऐसा लगता है कि यह तीन सामान्य मामलों को मापता है, जब वास्तव में यह एक, विशिष्ट मामले को मापता है।
यशवित

1
@tmyklebu मुझे गलत मत समझो, मैंने सवाल उठाया, यह जवाब और तुम्हारा जवाब। लेकिन मैं आपके इस कथन से असहमत हूं कि @chrylis उस अंतर को मापने के लिए बेंचमार्क को समायोजित कर रहा है जो इसे मापने की कोशिश कर रहा है। ओपी मुझे सही कर सकता है अगर मैं गलत हूं, लेकिन ऐसा नहीं लगता है कि वे केवल / मुख्य रूप से मापने की कोशिश कर रहे हैं == 0, जो बेंचमार्क परिणामों का एक बड़ा हिस्सा प्रतीत होता है। मुझे इस बात की अधिक संभावना है कि ओपी अधिक सामान्य श्रेणी के संचालन को मापने की कोशिश कर रहा है, और यह उत्तर बताता है कि बेंचमार्क उन सभी कार्यों में से एक के प्रति अत्यधिक तिरछा है।
यशवित

2
@tmyklebu बिल्कुल नहीं। मैं मूल कारणों को समझने के लिए हूं। लेकिन, पहचानने का एक प्रमुख कारण यह है कि बेंचमार्क को तिरछा किया गया था, यह तिरछा हटाने के लिए बेंचमार्क को बदलने के लिए अमान्य नहीं है, साथ ही उस तिरछी खुदाई के बारे में और अधिक समझने के लिए (उदाहरण के लिए, कि यह अधिक कुशल सक्षम कर सकता है) बाइटकोड, कि यह छोरों को अनियंत्रित करना आसान बना सकता है, आदि)। इसलिए मैंने इस उत्तर को (जो तिरछा पहचाना) और तुम्हारा (जो अधिक विस्तार से तिरछा खोदता है) दोनों को उखाड़ फेंका।
यशवित

8

जावा वर्चुअल मशीन में डेटा की मूल इकाई शब्द है। जेवीएम के कार्यान्वयन पर सही शब्द आकार चुनना शेष है। एक जेवीएम कार्यान्वयन को 32 बिट्स का न्यूनतम शब्द आकार चुनना चाहिए। यह दक्षता हासिल करने के लिए एक उच्च शब्द आकार चुन सकता है। न तो कोई प्रतिबंध है कि 64 बिट JVM केवल 64 बिट शब्द का चयन करे।

अंतर्निहित आर्किटेक्चर नियम नहीं करता है कि शब्द का आकार भी समान होना चाहिए। JVM डेटा शब्द को शब्द द्वारा पढ़ता / लिखता है। यही कारण है कि यह एक इंट की तुलना में लंबे समय तक हो सकता है ।

यहां आप एक ही विषय पर अधिक जानकारी पा सकते हैं।


4

मैंने सिर्फ कैलीपर का उपयोग करके एक बेंचमार्क लिखा है ।

परिणाम का उपयोग कर के लिए एक ~ 12x speedup: मूल कोड के साथ काफी संगत कर रहे हैं intसे अधिक long। यह निश्चित रूप से लगता है कि tmyklebu द्वारा रिपोर्ट किए गए लूप अनियंत्रित या कुछ इसी तरह चल रहा है।

timeIntDecrements         195,266,845.000
timeLongDecrements      2,321,447,978.000

यह मेरा कोड है; ध्यान दें कि यह एक ताज़ा-निर्मित स्नैपशॉट का उपयोग करता है caliper, क्योंकि मैं यह पता नहीं लगा सका कि उनके मौजूदा बीटा रिलीज़ के खिलाफ कैसे कोड किया जाए।

package test;

import com.google.caliper.Benchmark;
import com.google.caliper.Param;

public final class App {

    @Param({""+1}) int number;

    private static class IntTest {
        public static int v;
        public static void reset() {
            v = Integer.MAX_VALUE;
        }
        public static boolean decrementAndCheck() {
            return --v < 0;
        }
    }

    private static class LongTest {
        public static long v;
        public static void reset() {
            v = Integer.MAX_VALUE;
        }
        public static boolean decrementAndCheck() {
            return --v < 0;
        }
    }

    @Benchmark
    int timeLongDecrements(int reps) {
        int k=0;
        for (int i=0; i<reps; i++) {
            LongTest.reset();
            while (!LongTest.decrementAndCheck()) { k++; }
        }
        return (int)LongTest.v | k;
    }    

    @Benchmark
    int timeIntDecrements(int reps) {
        int k=0;
        for (int i=0; i<reps; i++) {
            IntTest.reset();
            while (!IntTest.decrementAndCheck()) { k++; }
        }
        return IntTest.v | k;
    }
}

1

रिकॉर्ड के लिए, यह संस्करण एक क्रूड "वार्मअप" करता है:

public class LongSpeed {

    private static long i = Integer.MAX_VALUE;
    private static int j = Integer.MAX_VALUE;

    public static void main(String[] args) {

        for (int x = 0; x < 10; x++) {
            runLong();
            runWord();
        }
    }

    private static void runLong() {
        System.out.println("Starting the long loop");
        i = Integer.MAX_VALUE;
        long startTime = System.currentTimeMillis();
        while(!decrementAndCheckI()){

        }
        long endTime = System.currentTimeMillis();

        System.out.println("Finished the long loop in " + (endTime - startTime) + "ms");
    }

    private static void runWord() {
        System.out.println("Starting the word loop");
        j = Integer.MAX_VALUE;
        long startTime = System.currentTimeMillis();
        while(!decrementAndCheckJ()){

        }
        long endTime = System.currentTimeMillis();

        System.out.println("Finished the word loop in " + (endTime - startTime) + "ms");
    }

    private static boolean decrementAndCheckI() {
        return --i < 0;
    }

    private static boolean decrementAndCheckJ() {
        return --j < 0;
    }

}

समग्र समय में लगभग 30% का सुधार होता है, लेकिन दोनों के बीच का अनुपात लगभग समान रहता है।


@ टेडहॉप - मैंने खदान में लूप सीमा को बदलने की कोशिश की और यह अनिवार्य रूप से अपरिवर्तित रहा।
हॉट लिक्स

@ Techrocket9: मुझे intइस कोड के साथ समान संख्या ( 20 गुना अधिक तेज) मिलती है।
tmyklebu

1

रिकॉर्ड के लिए:

अगर मैं उपयोग करता हूँ

boolean decrementAndCheckLong() {
    lo = lo - 1l;
    return lo < -1l;
}

(परिवर्तित "l--" से "l = l - 1l") लंबे प्रदर्शन में ~ 50% तक सुधार


0

मेरे पास परीक्षण करने के लिए 64 बिट मशीन नहीं है, लेकिन बड़े अंतर से पता चलता है कि काम पर थोड़ा अधिक लंबे बायटेकोड से अधिक है।

मैं अपने 32-बिट 1.7.0_45 पर लंबे / इंट (4400 बनाम 4800ms) के लिए बहुत करीब से देखता हूं।

यह केवल एक अनुमान है , लेकिन मुझे दृढ़ता से संदेह है कि यह मेमोरी मिसलिग्न्मेंट पेनल्टी का प्रभाव है। संदेह की पुष्टि / इनकार करने के लिए, एक सार्वजनिक स्थैतिक int डमी = 0 जोड़ने का प्रयास करें; i की घोषणा से पहले । यह मेमोरी लेआउट में 4 बाइट्स से नीचे धकेल देगा और बेहतर प्रदर्शन के लिए इसे ठीक से संरेखित कर सकता है। इस मुद्दे के कारण नहीं होने की पुष्टि की।

संपादित करें: इसके पीछे तर्क यह है कि वीएम अपने अवकाश पर खेतों को फिर से नहीं जोड़ सकता है, ताकि इष्टतम संरेखण के लिए पैडिंग को जोड़ा जा सके, क्योंकि यह जेएनआई के साथ हस्तक्षेप कर सकता है (मामला नहीं)।


वीएम को निश्चित रूप से खेतों को फिर से व्यवस्थित करने और पैडिंग जोड़ने की अनुमति है।
हॉट लिक्स

जेएनआई को इन कष्टप्रद, धीमी गति से काम करने वाले तरीकों के माध्यम से वस्तुओं का उपयोग करना पड़ता है जो कि जीसी हो सकता है क्योंकि देशी कोड चल रहा है, वैसे भी कुछ अपारदर्शी हैंडल लेते हैं। यह खेतों को फिर से जोड़ने और पैडिंग जोड़ने के लिए बहुत स्वतंत्र है।
tmyklebu
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.