2016-06-22 9 views
24

यहाँ मेरी बेंचमार्क कोड है:क्यों Array.slice इतना है (चौंकाने वाला!) धीमा?

def bm(duration: Long)(f: => Unit)={ 
    val end = System.currentTimeMillis + duration 
    var count = 0 
    while(System.currentTimeMillis < end) { f; count += 1 } 
    count 
} 

val array = new scala.util.Random().alphanumeric.take(1000).toArray 

(1 to 20).map { _ => bm(1000) { array.slice(100,200) } }.sum/20 

कई बार चल रहा है, मैं लगातार प्रति सेकंड के बारे में 15 लाख स्लाइस की बॉलपार्क में नंबर प्राप्त करें। 1.4 और 1.6 के बीच।

अब, मैं यह कर:

implicit class FastSlicing(val a: Array[Char]) extends AnyVal { 
    def fastSlice(from: Int, until: Int) = Arrays.copyOfRange(a, from, until) 
} 
(1 to 20).map { _ => bm(1000) { array.fastSlice(100,200) } }.sum/20 

और परिणाम मैं 16 और 18 लाख के बीच प्रति सेकंड स्लाइस की है। यह 10 गुना से अधिक तेज़ है।

अब, मैं ट्रेड-ऑफ के बारे में सभी सामान्य तर्कों को जानता हूं कि स्कैला कार्यात्मक मुहावरे प्रदान करता है और कभी-कभी प्रदर्शन की लागत पर सुरक्षा टाइप करता है ... लेकिन इस मामले में, मुझे लगता है कि वे सभी उत्तर देने में विफल रहते हैं सरल प्रश्न: ArrayOps.slice क्यों ??? मुझे एहसास है कि जावा के आदिम सरणी के साथ जिस तरह से व्यवहार किया जाता है, वैसे ही कई समान कार्यान्वयन की आवश्यकता होती है, लेकिन यह वास्तव में एक मामूली परेशानी है, वास्तव में एक 10x प्रदर्शन हिट को न्यायसंगत बनाने के लिए वास्तव में एक सौदा-ब्रेकर की समस्या नहीं है।

.slice केवल एक उदाहरण है, अन्य सरणी ऑप्स भी एक ही समस्या से ग्रस्त प्रतीत होते हैं। ऐसा क्यों होना चाहिए?

val seq = new scala.util.Random().alphanumeric.take(1000).toIndexedSeq 
(1 to 20).map { _ => bm(1000) { seq.slice(100,200) } }.sum/20 

यह मेरे लिए प्रति सेकंड के बारे में 5-6 लाख स्लाइस करता है:

अद्यतन अब, यहाँ कुछ है कि मैं और भी अधिक चौंकाने वाला लगता है। लेकिन यह:

import scala.collections.JavaConversions._ 
(1 to 20).map { _ => bm(1000) { seq.subList(100,200) } }.sum/20 

12 से 15 मिलियन के बीच करता है! अनुमोदित, यह अराजकता के मामले में परिमाण अंतर का क्रम नहीं है, लेकिन (1) यहां शामिल प्राइमेटिव का कोई विशेष संचालन नहीं है, इसलिए जावा मानक टूलिंग का उपयोग करके इसे लागू करने के लिए यह पूरी तरह से तुच्छ होगा, और (2) संग्रह अपरिवर्तनीय है ... सूचकांक की एक श्रृंखला के संदर्भ में कितना मुश्किल हो सकता है ???

+1

क्या आपने पहले से ही उनके पीछे कोड देखा है? – Vale

+0

@ वैले हाँ, मेरे पास है। क्या आपने सवाल पढ़ा है? ;) – Dima

+1

मैंने किया, लेकिन वह रेखा नहीं मिल सकती जहां आपने कहा था कि आपने किया था। मैं समझ पढ़ने में बुरा हो सकता है। – Vale

उत्तर

2

इसे scala 2.12 में तय किया गया है।

+10

हाँ ... मेरे द्वारा: डी – Dima

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