मैं स्काला को देखने के लिए उत्सुक हूं, और एक मूल प्रश्न है कि मुझे इसका जवाब नहीं मिल रहा है: सामान्य तौर पर, क्या स्काला और जावा के बीच मेमोरी के प्रदर्शन और उपयोग में अंतर है?
मैं स्काला को देखने के लिए उत्सुक हूं, और एक मूल प्रश्न है कि मुझे इसका जवाब नहीं मिल रहा है: सामान्य तौर पर, क्या स्काला और जावा के बीच मेमोरी के प्रदर्शन और उपयोग में अंतर है?
जवाबों:
स्केला को बहुत अधिक मात्रा में मेमोरी का उपयोग करने के लिए इसे साकार किए बिना बहुत आसान बनाता है। यह आमतौर पर बहुत शक्तिशाली है, लेकिन कभी-कभी कष्टप्रद हो सकता है। उदाहरण के लिए, मान लें कि आपके पास स्ट्रिंग्स (कहा जाता है array
) का एक सरणी है , और उन स्ट्रिंग्स से फाइलों तक (मैप mapping
) कहा जाता है । आप सभी फ़ाइलें है कि नक्शे में हैं और दो से अधिक से अधिक लंबाई के तार से आते हैं प्राप्त करना चाहते हैं मान लीजिए। जावा में, आप कर सकते हैं
int n = 0;
for (String s: array) {
if (s.length > 2 && mapping.containsKey(s)) n++;
}
String[] bigEnough = new String[n];
n = 0;
for (String s: array) {
if (s.length <= 2) continue;
bigEnough[n++] = map.get(s);
}
वाह! कठोर परिश्रम। स्काला में, समान कार्य करने का सबसे कॉम्पैक्ट तरीका है:
val bigEnough = array.filter(_.length > 2).flatMap(mapping.get)
आसान! लेकिन, जब तक आप इस बात से पूरी तरह परिचित नहीं हो जाते हैं कि संग्रह कैसे काम करता है, तो आप जो महसूस नहीं कर सकते हैं, वह यह है कि ऐसा करने का यह तरीका एक अतिरिक्त मध्यवर्ती सरणी (के साथ filter
) बना है, और सरणी के प्रत्येक तत्व के लिए एक अतिरिक्त ऑब्जेक्ट (साथ mapping.get
, जो वापस लौटता है) एक विकल्प)। यह दो फ़ंक्शन ऑब्जेक्ट्स (एक फ़िल्टर के लिए और एक फ़्लैटमैप के लिए भी) बनाता है, हालांकि फ़ंक्शन ऑब्जेक्ट्स के छोटे होने के बाद से यह शायद ही कभी एक प्रमुख मुद्दा है।
तो मूल रूप से, मेमोरी का उपयोग एक आदिम स्तर पर, समान है। लेकिन स्काला के पुस्तकालयों में कई शक्तिशाली विधियां हैं जो आपको (आमतौर पर अल्पकालिक) वस्तुओं की बड़ी संख्या को बहुत आसानी से बनाने देती हैं। कचरा इकट्ठा करने वाला आमतौर पर उस तरह के कचरे से बहुत अच्छा होता है, लेकिन अगर आप पूरी तरह से इस बात से बेखबर हो जाते हैं कि किस मेमोरी का इस्तेमाल किया जा रहा है, तो आप शायद जावा की तुलना में जल्द ही स्केला में मुश्किल में पड़ जाएंगे।
ध्यान दें कि कंप्यूटर लैंग्वेज बेंचमार्क गेम स्कैला कोड जावा जैसी शैली पाने के लिए जावा जैसी शैली में लिखा गया है, और इस प्रकार जावा जैसी मेमोरी का उपयोग होता है। आप इसे स्काला में कर सकते हैं: यदि आप उच्च-प्रदर्शन जावा कोड की तरह दिखने के लिए अपना कोड लिखते हैं, तो यह उच्च-प्रदर्शन स्काला कोड होगा। (आप इसे अधिक मुहावरेदार स्काला शैली में लिखने में सक्षम हो सकते हैं और अभी भी अच्छा प्रदर्शन प्राप्त कर सकते हैं, लेकिन यह बारीकियों पर निर्भर करता है।)
मुझे उस समय को प्रोग्रामिंग में खर्च करना चाहिए, मेरा स्काला कोड आमतौर पर मेरे जावा कोड से अधिक तेज है क्योंकि स्काला में मुझे कम प्रयास के साथ थकाऊ नॉट-परफॉर्मेंस-क्रिटिकल पार्ट्स मिल सकते हैं, और अपना अधिक ध्यान एल्गोरिदम को अनुकूलित करने में लगाता है। प्रदर्शन-महत्वपूर्ण भागों के लिए कोड।
मैं एक नया उपयोगकर्ता हूँ, इसलिए मैं ऊपर रेक्स केर के जवाब के लिए एक टिप्पणी जोड़ने में सक्षम नहीं कर रहा हूँ ( "जवाब" करने के लिए नए उपयोगकर्ताओं को अनुमति देने के लिए नहीं, बल्कि "टिप्पणी" एक बहुत ही अजीब नियम btw है)।
मैंने साइन अप करने के लिए बस जवाब दिया "phew, Java is verbose and such hard work" insinuation of Rex's popular s। जब आप निश्चित रूप से अधिक संक्षिप्त स्काला कोड लिख सकते हैं, तो दिए गए जावा उदाहरण स्पष्ट रूप से फूला हुआ है। अधिकांश जावा डेवलपर्स कुछ इस तरह से कोड करेंगे:
List<String> bigEnough = new ArrayList<String>();
for(String s : array) {
if(s.length() > 2 && mapping.get(s) != null) {
bigEnough.add(mapping.get(s));
}
}
और हां, अगर हम यह ढोंग करने जा रहे हैं कि एक्लिप्स आपके लिए अधिकांश वास्तविक टाइपिंग नहीं करता है और यह कि हर चरित्र वास्तव में आपको बेहतर प्रोग्रामर बनाता है, तो आप इसे कोड कर सकते हैं:
List b=new ArrayList();
for(String s:array)
if(s.length()>2 && mapping.get(s) != null) b.add(mapping.get(s));
अब न केवल मैंने पूर्ण चर नाम और घुंघराले ब्रेस टाइप करने के लिए मुझे समय बचाने के लिए (गहरे एल्गोरिदम विचारों को सोचने के लिए 5 और सेकंड खर्च करने के लिए मुझे मुक्त करने के लिए) लिया, लेकिन मैं अपने कोड को मोटापे से होने वाली प्रतियोगिताओं में भी दर्ज कर सकता हूं और संभावित रूप से अतिरिक्त नकदी के लिए छुट्टिया।
Arrays.stream(array).map(mapping::get).filter(x->x!=null).toArray(File[]::new);
अपने स्कैला को जावा की तरह लिखें, और आप लगभग समान बाइटकोड से उत्सर्जित होने की उम्मीद कर सकते हैं - लगभग समान मैट्रिक्स के साथ।
अपरिवर्तनीय वस्तुओं और उच्च क्रम वाले कार्यों के साथ इसे और अधिक "मुहावरेदार" लिखें, और यह थोड़ा धीमा और थोड़ा बड़ा होगा। इस नियम के अंगूठे का एक अपवाद यह है कि जेनेरिक ऑब्जेक्ट्स का उपयोग करते समय जिसमें टाइप पैरामेट @specialised
एनोटेशन का उपयोग करते हैं, यह और भी बड़ा बायटेकोड बनाएगा जो बॉक्सिंग / अनबॉक्सिंग से बचकर जावा के प्रदर्शन को आगे बढ़ा सकता है।
यह भी ध्यान देने योग्य तथ्य है कि अधिक मेमोरी / कम गति एक अपरिहार्य व्यापार-बंद है जब कोड लिखा जाता है जिसे समानांतर में चलाया जा सकता है। जियोमैटिक स्काला कोड, विशिष्ट जावा कोड की तुलना में प्रकृति में कहीं अधिक घोषणात्मक है, और अक्सर .par
पूरी तरह से समानांतर होने से केवल 4 वर्ण ( ) दूर है।
तो अगर
क्या आप तब कहेंगे कि स्काला कोड अब तुलनात्मक रूप से 25% धीमा है, या 3x तेज है?
सही उत्तर इस बात पर निर्भर करता है कि आप "प्रदर्शन" को कैसे परिभाषित करते हैं :)
.par
2.9 में है।
.par
।
map
विधि का उपयोग नहीं करते हैं वे गायब हो जाएंगे।
कंप्यूटर भाषा बेंचमार्क गेम:
स्पीड टेस्ट जावा / स्काला 1.71 / 2.25
मेमोरी टेस्ट जावा / स्केला 66.55 / 80.81
तो, इस बेंचमार्क का कहना है कि जावा 24% तेज है और स्काला 21% अधिक मेमोरी का उपयोग करता है।
ऑल-इन-ऑल यह कोई बड़ी बात नहीं है और वास्तविक दुनिया के ऐप्स में कोई फर्क नहीं होना चाहिए, जहां अधिकांश समय डेटाबेस और नेटवर्क द्वारा खपत होती है।
निचला रेखा: यदि स्काला आपको और आपकी टीम (और जब आप छोड़ते हैं, तो प्रोजेक्ट लेने वाले लोग) अधिक उत्पादक होते हैं, तो आपको इसके लिए जाना चाहिए।
दूसरों ने इस सवाल का जवाब तंग छोरों के संबंध में दिया है, हालांकि रेक्स केर के उदाहरणों के बीच एक स्पष्ट प्रदर्शन अंतर है जो मैंने टिप्पणी की है।
यह जवाब वास्तव में उन लोगों पर लक्षित है जो डिजाइन दोष के रूप में तंग-पाश अनुकूलन की आवश्यकता की जांच कर सकते हैं।
मैं अपेक्षाकृत स्काला के नया हूँ लेकिन इसके बारे में लग रहा है (एक साल या के बारे में), इस प्रकार अब तक, यह है कि यह आप के लिए अनुमति देता है ठुकराने डिजाइन, कार्यान्वयन और निष्पादन के कई पहलुओं को अपेक्षाकृत आसानी से (पर्याप्त पृष्ठभूमि पढ़ने और प्रयोग के साथ :)
आस्थगित डिजाइन विशेषताएं:
आस्थगित कार्यान्वयन विशेषताएं:
आस्थगित निष्पादन सुविधाएँ: (क्षमा करें, कोई लिंक नहीं)
ये विशेषताएं, मेरे लिए, वे हैं जो हमें तेज, तंग अनुप्रयोगों के मार्ग को फैलाने में मदद करती हैं।
रेक्स केर के उदाहरणों में भिन्नता है कि निष्पादन के कौन से पहलू स्थगित हैं। जावा उदाहरण में, स्मृति का आबंटन तब तक स्थगित कर दिया जाता है जब तक कि आकार की गणना नहीं की जाती है, जहां स्केल उदाहरण मैपिंग लुकअप को समाप्त कर देता है। मेरे लिए, वे पूरी तरह से अलग एल्गोरिदम की तरह लग रहे हैं।
यहाँ मुझे लगता है कि अपने उदाहरण के लिए सेब के बराबर सेब अधिक है:
val bigEnough = array.collect({
case k: String if k.length > 2 && mapping.contains(k) => mapping(k)
})
कोई मध्यस्थ संग्रह, कोई Option
उदाहरण आदि भी यह संग्रह प्रकार को संरक्षित करता है इसलिए bigEnough
प्रकार है Array[File]
- Array
's collect
कार्यान्वयन शायद श्री केर के जावा कोड क्या करता है की तर्ज पर कुछ कर रहा है।
ऊपर बताई गई आस्थगित डिज़ाइन विशेषताएँ, जो कि Scala के संग्रह API डेवलपर्स को भी भविष्य में रिलीज़ में बिना API को तोड़े हुए उस तीव्र Array-विशिष्ट संग्रह कार्यान्वयन को कार्यान्वित करने की अनुमति देंगी। यह वही है जो मैं गति के मार्ग को फैलाने के साथ संदर्भित कर रहा हूं।
इसके अलावा:
val bigEnough = array.withFilter(_.length > 2).flatMap(mapping.get)
withFilter
विधि है कि मैं यहाँ का उपयोग किया है बजाय filter
फिक्स मध्यवर्ती संग्रह समस्या लेकिन वहां अभी भी विकल्प उदाहरण मुद्दा है।
स्काला में सरल निष्पादन की गति का एक उदाहरण लॉगिंग के साथ है।
जावा में हम कुछ इस तरह लिख सकते हैं:
if (logger.isDebugEnabled())
logger.debug("trace");
स्काला में, यह सिर्फ:
logger.debug("trace")
क्योंकि स्काला में डिबग करने के लिए संदेश पैरामीटर का प्रकार " => String
" है जो मैं एक पैरामीटर-कम फ़ंक्शन के रूप में सोचता हूं जो मूल्यांकन किए जाने पर निष्पादित होता है, लेकिन जिसे प्रलेखन पास-बाय-नाम कहता है।
EDIT {स्काला में कार्य ऑब्जेक्ट हैं इसलिए यहां एक अतिरिक्त ऑब्जेक्ट है। मेरे काम के लिए, एक तुच्छ वस्तु का वजन एक लॉग संदेश की संभावना का मूल्यांकन करने की संभावना को दूर करने के लायक है। }
यह कोड को तेज नहीं बनाता है, लेकिन यह तेजी से होने की अधिक संभावना बनाता है और हमें अन्य लोगों के कोड के माध्यम से जाने और सफाई करने का अनुभव कम होता है।
मेरे लिए, यह स्काला के भीतर एक सुसंगत विषय है।
हार्ड कोड कैप्चर करने में विफल रहता है कि स्केला क्यों तेज है, हालांकि यह थोड़ा संकेत देता है।
मुझे लगता है कि यह कोड री-यूज़ का संयोजन है और स्काला में कोड क्वालिटी की छत है।
जावा में, भयानक कोड को अक्सर एक असंगत गंदगी बनने के लिए मजबूर किया जाता है और इसलिए उत्पादन गुणवत्ता एपीआई के भीतर वास्तव में व्यवहार्य नहीं है क्योंकि अधिकांश प्रोग्रामर इसका उपयोग करने में सक्षम नहीं होंगे।
मुझे उच्च उम्मीद है कि स्काला हमारे बीच आइंस्टीन को अधिक सक्षम एपीआई को लागू करने की अनुमति दे सकती है, जो संभवतः डीएसएल के माध्यम से व्यक्त की जाती है। स्काला में मुख्य एपीआई पहले से ही इस रास्ते से बहुत दूर हैं।
इस विषय पर @higherkinded ons प्रस्तुति - स्काला प्रदर्शन विचार जो कुछ जावा / स्काला तुलना करता है।
उपकरण:
महान ब्लॉगपोस्ट:
जावा और स्काला दोनों ही JVM बायटेकोड तक संकलित हैं, इसलिए यह अंतर उतना बड़ा नहीं है। आपके द्वारा प्राप्त की जा सकने वाली सबसे अच्छी तुलना संभवतः कंप्यूटर भाषा के बेंचमार्क गेम पर है , जो अनिवार्य रूप से कहता है कि जावा और स्काला दोनों में समान मेमोरी उपयोग है। सूचीबद्ध कुछ बेंचमार्क पर जावा की तुलना में स्काला केवल थोड़ा धीमा है, लेकिन यह सिर्फ इसलिए हो सकता है क्योंकि कार्यक्रमों का कार्यान्वयन अलग है।
हालांकि वास्तव में, वे दोनों इतने करीब हैं कि यह चिंता करने लायक नहीं है। स्कैला जैसी अधिक अभिव्यंजक भाषा का उपयोग करके आपको मिलने वाली उत्पादकता में वृद्धि न्यूनतम (यदि कोई है) प्रदर्शन हिट की तुलना में बहुत अधिक है।
Java and Scala both compile down to JVM bytecode,
जो उस so
प्रश्न के कथन के साथ जोड़ दिया गया था जिसे diffence isn't that big.
मैं दिखाना चाहता था, कि so
यह केवल एक लफ्फाजी की चाल है, न कि एक तर्कपूर्ण निष्कर्ष।
जावा उदाहरण वास्तव में विशिष्ट एप्लिकेशन प्रोग्राम के लिए एक मुहावरा नहीं है। ऐसा अनुकूलित कोड सिस्टम लाइब्रेरी विधि में पाया जा सकता है। लेकिन तब यह सही प्रकार की एक सरणी का उपयोग करेगा, अर्थात फ़ाइल [] और एक IndexOutOfBoundsException नहीं फेंकेंगे। (गिनती और जोड़ने के लिए अलग-अलग फिल्टर की स्थिति)। मेरा संस्करण (हमेशा!) घुंघराले ब्रेसिज़ के साथ होगा (क्योंकि मैं एक बग को खोजने में एक घंटा बिताना पसंद नहीं करता हूं जिसे 2 सेकंड बचाने के लिए ग्रहण में एक ही कुंजी को मारने के लिए पेश किया गया था):
List<File> bigEnough = new ArrayList<File>();
for(String s : array) {
if(s.length() > 2) {
File file = mapping.get(s);
if (file != null) {
bigEnough.add(file);
}
}
}
लेकिन मैं आपको अपनी वर्तमान परियोजना से कई अन्य बदसूरत जावा कोड उदाहरण ला सकता हूं। मैंने कॉमन कॉपी से बचने की कोशिश की और कोडिंग की शैली को आम संरचनाओं और व्यवहार से अलग करके देखा।
मेरे अमूर्त DAO बेस क्लास में मैं सामान्य कैशिंग तंत्र के लिए एक सार इनर क्लास है। प्रत्येक ठोस मॉडल ऑब्जेक्ट प्रकार के लिए अमूर्त DAO बेस क्लास का एक उपवर्ग होता है, जिसमें आंतरिक वर्ग को उपविधि के लिए एक कार्यान्वयन प्रदान करने के लिए उप-वर्गित किया जाता है जो डेटाबेस से लोड होने पर व्यावसायिक ऑब्जेक्ट बनाता है। (हम ORM टूल का उपयोग नहीं कर सकते क्योंकि हम एक स्वामित्व API के माध्यम से किसी अन्य सिस्टम तक पहुँच प्राप्त करते हैं।)
यह उपवर्ग और तात्कालिकता कोड जावा में बिल्कुल भी स्पष्ट नहीं है और स्काला में बहुत पठनीय होगा।