जावा में, इंट की बजाय बाइट या शॉर्ट का उपयोग करना अधिक कुशल है और डबल के बजाय फ्लोट?


91

मैंने देखा है कि मैंने हमेशा int का उपयोग किया है और कोई फर्क नहीं पड़ता कि संख्या कितनी छोटी या बड़ी होनी चाहिए। जावा में तो, इसे और अधिक उपयोग करने के लिए सक्षम है byteया shortके बजाय intऔर floatके बजाय double?

तो मान लीजिए कि मेरे पास बहुत सारे चीटियों और युगल के साथ एक कार्यक्रम है। अगर मैं जानता था कि संख्या फिट होगी, तो क्या यह मेरी बाइट्स को शॉर्ट्स या बाइट्स में बदलने और बदलने के लायक होगा?

मुझे पता है कि जावा में अहस्ताक्षरित प्रकार नहीं हैं, लेकिन क्या कुछ अतिरिक्त है अगर मैं जानता था कि संख्या केवल सकारात्मक होगी?

कुशल से मेरा मतलब ज्यादातर प्रोसेसिंग से है। मुझे लगता है कि कचरा संग्रहकर्ता बहुत तेज होगा यदि सभी चर आधे आकार के होंगे और गणना कुछ हद तक तेज होगी। (मुझे लगता है कि जब से मैं Android पर काम कर रहा हूँ मुझे कुछ हद तक राम के बारे में भी चिंता करने की ज़रूरत है)

(मुझे लगता है कि कचरा कलेक्टर केवल वस्तुओं के साथ व्यवहार करता है और आदिम नहीं है, लेकिन अभी भी परित्यक्त वस्तुओं में सभी प्राथमिकताओं को हटा देता है?)

मैंने इसे एक छोटे से एंड्रॉइड ऐप के साथ आज़माया, लेकिन वास्तव में मुझे बिल्कुल भी फर्क नहीं पड़ा। (हालांकि मैं "वैज्ञानिक रूप से" कुछ भी मापता नहीं था।)

क्या मैं यह मानने में गलत हूं कि यह तेज और अधिक कुशल होना चाहिए? मैं अपना समय बर्बाद करने के लिए एक बड़े पैमाने पर कार्यक्रम के माध्यम से जाने और सब कुछ बदलने से नफरत करता हूं।

जब मैं एक नई परियोजना शुरू करूंगा तो क्या यह शुरू से ही करने योग्य होगा? (मेरा मतलब है कि मुझे लगता है कि हर छोटी मदद करेगा, लेकिन फिर अगर ऐसा है, तो ऐसा क्यों नहीं लगता कि कोई भी ऐसा करता है।)

जवाबों:


107

क्या मैं यह मानने में गलत हूं कि यह तेज और अधिक कुशल होना चाहिए? मैं अपना समय बर्बाद करने के लिए एक बड़े पैमाने पर कार्यक्रम के माध्यम से जाने और सब कुछ बदलने से नफरत करता हूं।

संक्षिप्त जवाब

हां, आप गलत हैं। ज्यादातर मामलों में, उपयोग की जाने वाली जगह के संदर्भ में यह बहुत कम फर्क पड़ता है।

यह इसे ऑप्टिमाइज़ करने की कोशिश करने लायक नहीं है ... जब तक आपके पास स्पष्ट सबूत न हों कि ऑप्टिमाइज़ेशन की आवश्यकता है। और यदि आपको विशेष रूप से ऑब्जेक्ट फ़ील्ड के मेमोरी उपयोग को अनुकूलित करने की आवश्यकता है, तो आपको संभवतः अन्य (अधिक प्रभावी) उपाय करने की आवश्यकता होगी।

लंबा उत्तर

जावा वर्चुअल मशीन मॉडल ऑफ़सेट्स का उपयोग करके स्टैक और ऑब्जेक्ट फ़ील्ड्स जो (प्रभाव में) एक 32 बिट आदिम सेल आकार के गुणक हैं। इसलिए जब आप स्थानीय वेरिएबल या ऑब्जेक्ट फील्ड को (जैसे) ए घोषित करते हैं byte, तो वेरिएबल / फील्ड को 32 बिट सेल में स्टोर किया जाएगा, जैसे ए int

इसके दो अपवाद हैं:

  • longऔर doubleमानों के लिए 2 आदिम 32-बिट कोशिकाओं की आवश्यकता होती है
  • आदिम प्रकार के सरणियों को पैक रूप में दर्शाया जाता है, ताकि (उदाहरण के लिए) बाइट्स की एक सरणी प्रति 32 बिट शब्द में 4 बाइट्स रखती है।

तो यह और ... और आदिम के बड़े सरणियों के उपयोग को अनुकूलित करने के लायक हो सकता है । लेकिन सामान्य तौर पर नहीं।longdouble

सिद्धांत रूप में, एक JIT इसे अनुकूलित करने में सक्षम हो सकता है, लेकिन व्यवहार में मैंने कभी ऐसा JIT के बारे में नहीं सुना जो ऐसा करता हो। एक बाधा यह है कि आमतौर पर JIT तब तक नहीं चल सकती है जब तक कि संकलित किए जाने वाले वर्ग के उदाहरण नहीं बने हैं। यदि JIT मेमोरी लेआउट को अनुकूलित करता है, तो आप एक ही कक्षा के ऑब्जेक्ट के दो (या अधिक) "फ्लेवर" रख सकते हैं ... और यह बहुत बड़ी मुश्किल पेश करेगा।


Revisitation

@ मेरिटॉन के उत्तर में बेंचमार्क परिणामों को देखते हुए, यह प्रतीत होता है कि उपयोग करने के बजाय shortऔर गुणन के लिए एक प्रदर्शन जुर्माना लगाता है। वास्तव में, यदि आप अलगाव में संचालन पर विचार करते हैं, तो जुर्माना महत्वपूर्ण है। (आप उन्हें अलगाव में विचार नहीं करना चाहिए ... लेकिन यह एक और विषय है।)byteint

मुझे लगता है कि स्पष्टीकरण यह है कि जेआईटी संभवत: प्रत्येक मामले में 32 बिट का गुणा निर्देश का उपयोग कर गुणा कर रही है। लेकिन byteऔर shortमामले में, यह मध्यवर्ती निर्देश 32 बिट मान को या प्रत्येक लूप पुनरावृत्ति में परिवर्तित करने के लिए अतिरिक्त निर्देशों को निष्पादित करता है । (सिद्धांत रूप में, यह रूपांतरण एक बार लूप के अंत में किया जा सकता है ... लेकिन मुझे संदेह है कि ऑप्टिमाइज़र यह पता लगाने में सक्षम होगा।)byteshort

वैसे भी, यह एक और समस्या के लिए स्विचन के साथ shortऔर byteएक अनुकूलन के रूप में इंगित करता है । यह प्रदर्शन को बदतर बना सकता है ... एक एल्गोरिथ्म में जो अंकगणित है और गहन गणना करता है।


30
+1 जब तक आप एक प्रदर्शन समस्या का स्पष्ट सबूत है अनुकूलित न करें
बोहेमियन

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

@meriton - मुझे पूरा यकीन है कि ऑब्जेक्ट लेआउट क्लास लोड समय पर निर्धारित किए जाते हैं , और वे उसके बाद नहीं बदलते हैं। मेरे उत्तर का "फाइन-प्रिंट" भाग देखें। यदि कोड के JITed होने पर वास्तविक मेमोरी लेआउट बदल गए, तो JVM के लिए निपटना वास्तव में मुश्किल होगा। (जब मैंने कहा कि जेआईटी लेआउट का अनुकूलन कर सकता है , तो यह काल्पनिक और अव्यवहारिक है ... जो समझा सकता है कि मैंने वास्तव में ऐसा करने के बारे में जेआईटी के बारे में कभी नहीं सुना है।)
स्टीफन सी

मुझे पता है। मैं सिर्फ यह बताना चाह रहा था कि भले ही ऑब्जेक्ट्स बनने के बाद मेमोरी लेआउट को बदलना मुश्किल हो, लेकिन एक जेवीएम अभी भी मेमोरी लेआउट को ऑप्टिमाइज़ कर सकता है, यानी क्लास लोड टाइम पर। अलग तरीके से कहें, कि JVM कल्पना शब्द के साथ एक JVM के व्यवहार का वर्णन करता है जरूरी नहीं कि एक JVM को उस तरह से लागू करने की आवश्यकता है - हालांकि सबसे अधिक संभवतः हैं।
Meriton

@meriton - JVM युक्ति स्थानीय फ्रेम / ऑब्जेक्ट के भीतर "वर्चुअल मशीन वर्ड ऑफ़सेट" के बारे में बात कर रही है। इन्हें भौतिक मशीन से कैसे मैप किया जाता है, यह निर्दिष्ट नहीं किया गया है। वास्तव में, यह इसे निर्दिष्ट नहीं कर सकता ... क्योंकि हार्डवेयर-विशिष्ट क्षेत्र संरेखण आवश्यकताओं हो सकता है।
स्टीफन सी

29

यह जेवीएम के कार्यान्वयन पर निर्भर करता है, साथ ही साथ अंतर्निहित हार्डवेयर भी। अधिकांश आधुनिक हार्डवेयर मेमोरी से सिंगल बाइट नहीं लाएंगे (या पहले स्तर के कैश से भी), यानी छोटे आदिम प्रकारों का उपयोग करने से आमतौर पर मेमोरी बैंडविड्थ की खपत कम नहीं होती है। इसी तरह, आधुनिक सीपीयू का शब्द आकार 64 बिट्स है। वे कम बिट्स पर ऑपरेशन कर सकते हैं, लेकिन यह अतिरिक्त बिट्स को त्यागकर काम करता है, जो या तो तेज नहीं है।

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

आम तौर पर हालांकि, छोटे आदिम प्रकारों का उपयोग करना तेज नहीं है।

यह प्रदर्शित करने के लिए, निम्नलिखित बेंचमार्क निहारें:

package tools.bench;

import java.math.BigDecimal;

public abstract class Benchmark {

    final String name;

    public Benchmark(String name) {
        this.name = name;
    }

    abstract int run(int iterations) throws Throwable;

    private BigDecimal time() {
        try {
            int nextI = 1;
            int i;
            long duration;
            do {
                i = nextI;
                long start = System.nanoTime();
                run(i);
                duration = System.nanoTime() - start;
                nextI = (i << 1) | 1; 
            } while (duration < 100000000 && nextI > 0);
            return new BigDecimal((duration) * 1000 / i).movePointLeft(3);
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }   

    @Override
    public String toString() {
        return name + "\t" + time() + " ns";
    }

    public static void main(String[] args) throws Exception {
        Benchmark[] benchmarks = {
            new Benchmark("int multiplication") {
                @Override int run(int iterations) throws Throwable {
                    int x = 1;
                    for (int i = 0; i < iterations; i++) {
                        x *= 3;
                    }
                    return x;
                }
            },
            new Benchmark("short multiplication") {                   
                @Override int run(int iterations) throws Throwable {
                    short x = 0;
                    for (int i = 0; i < iterations; i++) {
                        x *= 3;
                    }
                    return x;
                }
            },
            new Benchmark("byte multiplication") {                   
                @Override int run(int iterations) throws Throwable {
                    byte x = 0;
                    for (int i = 0; i < iterations; i++) {
                        x *= 3;
                    }
                    return x;
                }
            },
            new Benchmark("int[] traversal") {                   
                @Override int run(int iterations) throws Throwable {
                    int[] x = new int[iterations];
                    for (int i = 0; i < iterations; i++) {
                        x[i] = i;
                    }
                    return x[x[0]];
                }
            },
            new Benchmark("short[] traversal") {                   
                @Override int run(int iterations) throws Throwable {
                    short[] x = new short[iterations];
                    for (int i = 0; i < iterations; i++) {
                        x[i] = (short) i;
                    }
                    return x[x[0]];
                }
            },
            new Benchmark("byte[] traversal") {                   
                @Override int run(int iterations) throws Throwable {
                    byte[] x = new byte[iterations];
                    for (int i = 0; i < iterations; i++) {
                        x[i] = (byte) i;
                    }
                    return x[x[0]];
                }
            },
        };
        for (Benchmark bm : benchmarks) {
            System.out.println(bm);
        }
    }
}

जो मेरी कुछ पुरानी नोटबुक पर प्रिंट करता है (कॉलम समायोजित करने के लिए रिक्त स्थान जोड़ रहा है):

int       multiplication    1.530 ns
short     multiplication    2.105 ns
byte      multiplication    2.483 ns
int[]     traversal         5.347 ns
short[]   traversal         4.760 ns
byte[]    traversal         2.064 ns

जैसा कि आप देख सकते हैं, प्रदर्शन अंतर काफी मामूली हैं। एल्गोरिदम का अनुकूलन आदिम प्रकार की पसंद से कहीं अधिक महत्वपूर्ण है।


3
"सबसे विशेष रूप से सरणियों का उपयोग करते समय" कहने के बजाय, मुझे लगता है कि यह कहना सरल हो सकता है shortऔर byteअधिक कुशल होते हैं जब सरणियों में संग्रहीत होते हैं जो कि पदार्थ से काफी बड़े होते हैं (बड़े सरणी, बड़ा दक्षता अंतर;) byte[2]अधिक हो सकता है या उससे कम कुशल int[2], लेकिन किसी भी तरह से पर्याप्त नहीं है), लेकिन यह कि व्यक्तिगत मूल्य अधिक कुशलता से संग्रहीत हैं int
सुपरकैट

2
मैंने क्या जाँच की: उन बेंचमार्क ने हमेशा एक int ('3') को फैक्टर या असाइनमेंट ऑपरेंड (लूप वेरिएंट, फिर कास्ट) के रूप में इस्तेमाल किया। मैंने जो किया था उसका उपयोग टाइप किए गए कारकों / असाइनमेंट ऑपरेंड्स के आधार पर किया गया था: लैवल्यू प्रकार के आधार पर: इंट मल्टी 76.481 एनएस इंट मल्टी (टाइप्ड) 72.581 एनएस शॉर्ट मल्टी 87.908 एनएस शॉर्ट मल्टी (टाइप्ड) 90.7.7 एनएस बाइट मल्टी 87.859 एनएस बाइट मल्टी (टाइप्ड) 89.524 एनएस int [] trav 88.905 ns int [] trav (टाइप किया हुआ) n ९ .१२६ एनएस छोटा [] trav १०.५६३ ns छोटा [] trav (टाइप किया हुआ) १०.०३ ९ ns बाइट [] trav n.२५६ nte बाइट [] trav (टाइप किया गया) 38.३३ 88 ns मुझे लगता है कि वहाँ है अनावश्यक कास्टिंग के बहुत सारे। वे परीक्षण एक Android टैब पर चलाए गए थे।
बॉन्डैक्स

5

का उपयोग byteकरने के बजाय intअगर आप उन्हें एक बड़ी राशि में उपयोग कर रहे हैं प्रदर्शन बढ़ा सकते हैं। यहाँ एक प्रयोग है:

import java.lang.management.*;

public class SpeedTest {

/** Get CPU time in nanoseconds. */
public static long getCpuTime() {
    ThreadMXBean bean = ManagementFactory.getThreadMXBean();
    return bean.isCurrentThreadCpuTimeSupported() ? bean
            .getCurrentThreadCpuTime() : 0L;
}

public static void main(String[] args) {
    long durationTotal = 0;
    int numberOfTests=0;

    for (int j = 1; j < 51; j++) {
        long beforeTask = getCpuTime();
        // MEASURES THIS AREA------------------------------------------
        long x = 20000000;// 20 millions
        for (long i = 0; i < x; i++) {
                           TestClass s = new TestClass(); 

        }
        // MEASURES THIS AREA------------------------------------------
        long duration = getCpuTime() - beforeTask;
        System.out.println("TEST " + j + ": duration = " + duration + "ns = "
                + (int) duration / 1000000);
        durationTotal += duration;
        numberOfTests++;
    }
    double average = durationTotal/numberOfTests;
    System.out.println("-----------------------------------");
    System.out.println("Average Duration = " + average + " ns = "
            + (int)average / 1000000 +" ms (Approximately)");


}

}

यह वर्ग एक नया बनाने की गति का परीक्षण करता है TestClass। प्रत्येक परीक्षण इसे 20 मिलियन बार करता है और 50 परीक्षण होते हैं।

यहाँ TestClass है:

 public class TestClass {
     int a1= 5;
     int a2= 5; 
     int a3= 5;
     int a4= 5; 
     int a5= 5;
     int a6= 5; 
     int a7= 5;
     int a8= 5; 
     int a9= 5;
     int a10= 5; 
     int a11= 5;
     int a12=5; 
     int a13= 5;
     int a14= 5; 
 }

मैंने SpeedTestकक्षा चलाई है और अंत में इसे मिला है:

 Average Duration = 8.9625E8 ns = 896 ms (Approximately)

अब मैं टेस्टक्लास में बट्स को बाइट्स में बदल रहा हूं और इसे फिर से चला रहा हूं। यहाँ परिणाम है:

 Average Duration = 6.94375E8 ns = 694 ms (Approximately)

मेरा मानना ​​है कि इस प्रयोग से पता चलता है कि यदि आप बड़ी मात्रा में वेरिएबल का उपयोग कर रहे हैं, तो इंट के बजाय बाइट का उपयोग करने से दक्षता बढ़ सकती है


4
ध्यान दें कि यह बेंचमार्क केवल आवंटन और निर्माण से जुड़ी लागतों को माप रहा है, और केवल एक वर्ग का मामला है जिसमें बहुत सारे व्यक्तिगत क्षेत्र हैं। यदि अंकगणित / अद्यतन संचालन को खेतों पर किया गया था, तो @ मेरिटॉन के परिणाम बताते हैं कि byte>> << << से धीमा हो सकता है int
स्टीफन सी

सच है, मुझे इसे स्पष्ट करने के लिए इसे बेहतर शब्द देना चाहिए था।
21

2

बाइट को आम तौर पर 8 बिट माना जाता है। शॉर्ट को आमतौर पर 16 बिट्स माना जाता है।

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

हालाँकि, आपका कंप्यूटर शायद 8 बिट नहीं है, और यह शायद 16 बिट नहीं है। इसका मतलब यह है कि विशेष रूप से 16 या 8 बिट्स प्राप्त करने के लिए, "ट्रिकरी" का सहारा लेना होगा, जो समय को बर्बाद करने का दिखावा करता है ताकि जरूरत पड़ने पर उन प्रकारों को एक्सेस करने की क्षमता हो।

इस बिंदु पर, यह निर्भर करता है कि हार्डवेयर कैसे लागू किया जाता है। हालाँकि, जब से मुझे खरीदा गया है, सबसे अच्छी गति उन चीज़ों को संग्रहीत करने से प्राप्त हुई है जो आपके CPU के उपयोग के लिए आरामदायक हैं। 64 बिट प्रोसेसर 64 बिट तत्वों के साथ काम करना पसंद करता है, और इससे कम कुछ भी अक्सर "इंजीनियरिंग जादू" की आवश्यकता होती है यह दिखावा करने के लिए कि यह उनके साथ काम करना पसंद करता है।


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

मैं कल्पना कर सकता हूं कि यह सच है। मुझे बस याद है कि मोटोरोला 68k सिम्युलेटर में हमने इस्तेमाल किया था, अधिकांश ऑपरेशन 16 बिट मूल्यों के साथ काम कर सकते थे, जबकि 32 बिट या 64 बिट के साथ नहीं। मैं सोच रहा था कि इसका मतलब यह था कि सिस्टम का पसंदीदा मूल्य आकार था कि यह आशातीत रूप से प्राप्त कर सकता है। हालांकि मैं सोच सकता हूं कि आधुनिक 64 बिट प्रोसेसर 8 बिट, 16 बिट, 32 बिट और 64 बिट को समान आसानी से प्राप्त कर सकते हैं, इस मामले में यह एक गैर है। यह बात बताने के लिए धन्यवाद।
दिमित्री

"... आमतौर पर माना जाता है ..." - वास्तव में, यह स्पष्ट रूप से, स्पष्ट रूप से >> निर्दिष्ट << उन आकारों के होने के लिए है। जावा में। और इस प्रश्न का संदर्भ जावा है।
स्टीफन सी

बड़ी संख्या में प्रोसेसर यहां तक ​​कि समान आकार वाले डेटा को हेरफेर करने और एक्सेस करने के लिए समान संख्या में चक्रों का उपयोग करते हैं, इसलिए यह वास्तव में चिंता का विषय नहीं है जब तक कि आप किसी विशेष जेवीएम और प्लेटफॉर्म पर माप नहीं लेते।
ड्रोब

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

2

शॉर्ट / बाइट / चार के कम प्रदर्शन का एक कारण इन डेटा प्रकारों के लिए सीधे समर्थन की कमी है। प्रत्यक्ष समर्थन से, इसका मतलब है, जेवीएम विनिर्देशों में इन डेटा प्रकारों के लिए कोई निर्देश निर्धारित नहीं है। स्टोर, लोड, ऐड आदि जैसे निर्देशों में इंट डेटा टाइप के लिए संस्करण हैं। लेकिन उनके पास लघु / बाइट / चार के लिए संस्करण नहीं हैं। उदा नीचे जावा कोड पर विचार करें:

void spin() {
 int i;
 for (i = 0; i < 100; i++) {
 ; // Loop body is empty
 }
}

समान नीचे दिए गए मशीन कोड में परिवर्तित हो जाता है।

0 iconst_0 // Push int constant 0
1 istore_1 // Store into local variable 1 (i=0)
2 goto 8 // First time through don't increment
5 iinc 1 1 // Increment local variable 1 by 1 (i++)
8 iload_1 // Push local variable 1 (i)
9 bipush 100 // Push int constant 100
11 if_icmplt 5 // Compare and loop if less than (i < 100)
14 return // Return void when done

अब, नीचे के रूप में संक्षिप्त को बदलने पर विचार करें।

void sspin() {
 short i;
 for (i = 0; i < 100; i++) {
 ; // Loop body is empty
 }
}

संबंधित मशीन कोड निम्नानुसार बदल जाएगा:

0 iconst_0
1 istore_1
2 goto 10
5 iload_1 // The short is treated as though an int
6 iconst_1
7 iadd
8 i2s // Truncate int to short
9 istore_1
10 iload_1
11 bipush 100
13 if_icmplt 5
16 return

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

अब, इस प्रकार प्रत्यक्ष समर्थन न देने का कारण बताया गया है:

जावा वर्चुअल मशीन टाइप इंट के डेटा के लिए सबसे सीधा समर्थन प्रदान करता है। यह आंशिक रूप से जावा वर्चुअल मशीन के ऑपरेंड स्टैक और स्थानीय चर सरणियों के कुशल कार्यान्वयन की प्रत्याशा में है। यह विशिष्ट कार्यक्रमों में इंट डेटा की आवृत्ति से भी प्रेरित है। अन्य अभिन्न प्रकारों का प्रत्यक्ष समर्थन कम है। उदाहरण के लिए, स्टोर का कोई बाइट, चार या लघु संस्करण नहीं हैं, लोड या निर्देश जोड़ें।

यहाँ मौजूद JVM विनिर्देशन से उद्धृत (पृष्ठ 58)।


ये डिसेबल्ड बायोटेक हैं; यानी जेवीएम वर्चुअल निर्देश। वे javacसंकलक द्वारा अनुकूलित नहीं हैं , और आप उन पर कोई विश्वसनीय निष्कर्ष नहीं निकाल सकते हैं कि कार्यक्रम वास्तविक जीवन में कैसा प्रदर्शन करेगा। JIT कंपाइलर इन बायोटेक को वास्तविक देशी मशीन निर्देशों के लिए संकलित करता है, और इस प्रक्रिया में कुछ बहुत गंभीर अनुकूलन करता है। यदि आप कोड के प्रदर्शन का विश्लेषण करना चाहते हैं , तो आपको मूल कोड निर्देशों की जांच करने की आवश्यकता है। (और यह जटिल है क्योंकि आपको एक बहु-चरण x86_64 पाइपलाइन के समय व्यवहार को ध्यान में रखने की आवश्यकता है।)
स्टीफन सी

मेरा मानना ​​है कि जावा विनिर्देशन लागू करने के लिए javac कार्यान्वयनकर्ताओं के लिए हैं। इसलिए मुझे नहीं लगता कि उस स्तर पर कोई और अनुकूलन किया गया है। वैसे भी, मैं पूरी तरह से गलत भी हो सकता है। कृपया अपने बयान का समर्थन करने के लिए कुछ संदर्भ लिंक साझा करें।
मनीष बंसल

यहाँ मेरे कथन का समर्थन करने के लिए एक तथ्य है। आपको कोई भी (विश्वसनीय) टाइमिंग के आंकड़े नहीं मिलेंगे जो आपको बताते हैं कि प्रत्येक JVM बायटेकोड इंस्ट्रक्शन को कितने क्लॉक साइकिल देता है। निश्चित रूप से ओरेकल या अन्य जेवीएम आपूर्तिकर्ताओं द्वारा प्रकाशित नहीं किया गया है। इसके अलावा, stackoverflow.com/questions/1397009
स्टीफन सी

मुझे एक पुराना (2008) पेपर मिला, जहां किसी ने बायटेकोड अनुक्रमों के प्रदर्शन की भविष्यवाणी करने के लिए एक मंच स्वतंत्र मॉडल विकसित करने की कोशिश की। वे दावा करते हैं कि आरडीसीटीएस माप की तुलना में उनकी भविष्यवाणियां 25% तक बंद थीं .... एक पेंटियम पर। और वे JVM को JIT संकलन अक्षम के साथ चला रहे थे! संदर्भ: scirectirect.com/science/article/pii/S1571066108004581
स्टीफन सी

मैं यहाँ सिर्फ भ्रमित हूँ। क्या मेरा उत्तर उन तथ्यों का समर्थन करने में नहीं है, जिन्हें आपने पुनरीक्षण अनुभाग के तहत कहा है?
मनीष बंसल

0

अंतर शायद ही ध्यान देने योग्य है! यह डिजाइन, औचित्य, एकरूपता, आदत, आदि का सवाल है ... कभी-कभी यह सिर्फ स्वाद की बात है। जब तुम सब के बारे में परवाह है कि अपने कार्यक्रम और चल रहा है और प्रतिस्थापन एक उठ जाता है है floatएक के लिए intशुद्धता को नुकसान नहीं होगा, मैं एक के लिए जा रहा में कोई फायदा नहीं दिखता है या किसी अन्य जब तक आप प्रदर्शन कर सकते हैं कि किसी भी प्रकार बदलती जाए प्रदर्शन का उपयोग कर। 2 या 3 बाइट्स में भिन्न प्रकार के आधार पर ट्यूनिंग प्रदर्शन वास्तव में आखिरी चीज है जिसे आपको ध्यान देना चाहिए; डोनाल्ड नुथ ने एक बार कहा था: "समयपूर्व अनुकूलन सभी बुराई की जड़ है" (यह सुनिश्चित नहीं था कि यह उसका था, यदि आपके पास उत्तर है तो संपादित करें)।


5
Nit: A सभी पूर्णांक a का प्रतिनिधित्व float नहींint कर सकता; न ही intकिसी भी गैर-पूर्णांक मान का प्रतिनिधित्व floatकर सकता है। यही है, जबकि सभी अंतर मान लंबे मानों के सबसेट हैं, एक int एक उपसमूह का उपसमुच्चय नहीं है और एक तैरता एक int का सबसेट नहीं है।

मुझे उम्मीद है कि उत्तर देने वाला लिखने के लिए था substituting a float for a double, यदि उत्तरदाता को उत्तर को संपादित करना चाहिए। यदि उत्तरदाता को शर्म से सिर नहीं लटकाना चाहिए और @pst द्वारा उल्लिखित कारणों और कई अन्य कारणों से मूल बातों पर वापस जाना चाहिए।
उच्च प्रदर्शन मार्क

@HighPerformanceMark नहीं, मैंने इंट और फ्लोट लगाया क्योंकि यही मैं सोच रहा था। मेरा उत्तर जावा के लिए विशिष्ट नहीं है, हालांकि मैं सी सोच रहा था ... यह सामान्य होने का मतलब है। मतलब टिप्पणी आपको मिल गई।
mrk
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.