2016-06-18 4 views
6

जबकि Coursera से "स्केला विशेषज्ञता" होमवर्क करने मैं इस समस्या का सामना करना पड़ा (इस संस्करण सरल है और किसी भी होमवर्क विवरण शामिल नहीं है, यह सिर्फ सरणी ट्रेवर्सल है)स्काला पैटर्न मिलान प्रदर्शन

val chars: Array[Char] = some array 

def fun1(idx:Int):Int = { 
    some code here (including the stop condition) 

    val c = chars(idx) 
    c match{ 
     case '(' => fun1(idx+1) 
     case _ => fun1(idx+1) 
    } 

} 

इस कोड को 4 बार धीमी गति से

def fun2(idx: Int):Int = { 
    some code here (including the stop condition) 

    val c = chars(idx) 
    (c == '(') match{ 
     case true => fun2(idx+1) 
     case _ => fun2(idx+1) 
    } 
} 

सभी मैं कर रहा हूँ मिलान पैटर्न बदल रहा है (मैं इसे ScalMeter का उपयोग कर चला रहा हूँ तो मैं आंकड़ों में विश्वास करते हैं)।

क्या कोई इस व्यवहार को समझा सकता है?

उत्तर

2

मैं केवल पुष्टि कर सकता हूं कि पहले match ~ 50% धीमी है, न कि 4x (2.11.8)। वैसे भी यदि आप बाइटकोड को देखते हैं तो आप पाएंगे कि पहले match का अनुवाद tableswitch निर्देश में किया गया है, जिसका प्रयोग आम तौर पर जावा switch कथन के लिए कई विकल्पों के साथ किया जाता है और मूल रूप से एक लुकअप गोटो है, जबकि दूसरे का अनुवाद if पर किया जाता है। तो दूसरी match बस है:

if (c == '(') fun2(idx+1) else fun2(idx+1) 
0

अद्यतन नीचे गलत है (इन परीक्षणों में अधिकांश समय डेटा पैदा खर्च किया गया था, इसलिए वास्तविक ट्रेवर्सल समय में अंतर ध्यान देने योग्य नहीं था यह एक ही बेंचमार्क चल रहा है। लगातार इनपुट के साथ अन्य मामले के लिए case ')' मामले बनाम ~ 35ms के लिए प्रति 100 मिलियन प्रविष्टियों 125ms से पता चलता ~।)

मैं अंतर आप का वर्णन कर रहे हैं नहीं देख रहा हूँ। ,

def func(s: Seq[Char], idx: Int): String = 
    if(idx == s.length) "foo" else s(idx) match { 
    case ')' => func(s, idx+1) 
    case _ => func(s, idx+1) 
    } 

def func1(s: Seq[Char], idx: Int): String = 
    if(idx == s.length) "foo" else (s(idx) == '(') match { 
    case true => func(s, idx+1) 
    case _ => func(s, idx+1) 
    } 

import scala.util.Random 
def randy = Stream.continually(Random.nextPrintableChar) 


def doit(n: Int)(f: (Seq[Char], Int) => String) = { 
val start = System.currentTimeMillis;  
f(randy.take(n).toIndexedSeq, 0); 
System.currentTimeMillis - start 
} 


scala> doit(1000000)(func) 
res9: Long = 231 

scala> doit(1000000)(func1) 
res10: Long = 238 

scala> doit(1000000)(func) 
res11: Long = 234 

scala> doit(1000000)(func1) 
res12: Long = 201 

आदि आप देख सकते हैं: सुनिश्चित नहीं हैं कि ScalaMeter यह होता है, लेकिन repl में यह चल रहा है (दे "गरम" के बाद "सूखी" कई बार चलाकर), मैं वास्तव में एक ही प्रदर्शन प्राप्त कोई बड़ा अंतर नहीं।

+0

मुझे संदेह होगा कि यह मान्य बेंचमार्किंग विधि के पास कुछ भी है। स्कालामीटर परिणाम स्थिर होने तक दो दर्जनों गर्मियों की तरह करता है। आप एक ही डेटा का उपयोग करके परीक्षण भी नहीं करते हैं। –

+0

हाँ, वही डेटा नहीं। लेकिन मुझे रनों के बीच बहुत करीबी परिणाम मिल रहे हैं। Stddev बेहद कम है, जो बताता है कि अगर मैं एक ही डेटा का उपयोग करता हूं, तो मुझे बहुत अंतर दिखाई नहीं देगा। जैसा कि उत्तर में बताया गया है, मैंने गर्मजोशी भी किया है, इसलिए यह सुनिश्चित न करें कि इस बेंचमार्क के बारे में आपको "अमान्य" क्या लगता है। मैं अपने निष्कर्षों द्वारा खड़े हो जाओ, और उन्हें निर्णायक (और reproducibly) का खंडन करने के लिए आप को चुनौती है, तो आप कर सकते हैं। – Dima

+0

अपने कार्यों उधार, यहाँ स्केला मीटर के साथ बेंचमार्क है: https://gist.github.com/lukaszwawrzyk/a2505d5b3083bb72de51b8445fbb9a76 'देते चार समय: 13.172258374999998 ms' और' bool समय: ४.७३,९४,०४,५७५ ms'। यह प्रश्न में के रूप में सरणियों के लिए किया जाता है, तो का उपयोग कर एक अनुक्रमित seq परिणाम वास्तव में करीब नहीं बल्कि बराबर (95 सेकंड बनाम 80 सेकंड) –

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