2015-05-16 11 views
13

मैं जंग में बेंचमार्क निश्चित संचालनों के लिए करना चाहते हैं, लेकिन मैं लग रहे कुछ परेशानी हो रही किया जाना है रूबी में ऑपरेशन 4.5 सेकंड में खत्म:उत्पन्न तार और सबस्ट्रिंग की पहचान बहुत धीमी गति से

needle = 'b' * 100 
haystack = 'a' * 100_000 

puts 'Data ready.' 

1_000_000.times do 
    haystack.include? needle 
end 

मैं मदद नहीं कर सकता लेकिन लगता है कि मैं कुछ मौलिक रूप से गलत कर रहा हूँ। जंग में ऐसा करने का उचित तरीका क्या होगा?

rustc 1.0.0 (a59de37e9 2015-05-13) (built 2015-05-14) 
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux] 
+3

जो लोग आश्चर्य के लिए: इस मामले में, यह एक अनुकूलन मुद्दा नहीं है। यहां तक ​​कि जंग संस्करण पर ऑप्टिमाइज़ेशन के साथ भी चलने के लिए बहुत लंबा है। – Levans

+0

मैं * सोचता हूं * यह हो सकता है कि स्ट्रिंग के लिए 'शामिल' यूटीएफ -8 को सही तरीके से संभालने के लिए अतिरिक्त क्रियाएं करता है, हालांकि, जब मैं नियमित स्लाइस के लिए 'शामिल' की गति की जांच करने गया, तो मुझे पता चला कि जंग में एक भी नहीं है o_O। मेरा बेवकूफ कार्यान्वयन अभी भी बहुत धीमा था। –

+1

यह मेरे लिए प्रयास किया; रुबी ने 5 एस लिया, जंग ने * 7 मिनट * लिया। जंग के कार्यान्वयन के माध्यम से एक त्वरित squiz (देखें ['libcore/str/pattern.rs'] (https://github.com/rust-lang/rust/blob/1.0.0/src/libcore/str/pattern.rs# एल 3 9 0)) यह रस्ट के खोजकर्ता की तरह दिखता है * पूरी तरह से बेवकूफ़ *। यदि रूबी कार्यान्वयन कुछ भी दूरस्थ रूप से चालाक कर रहा है, तो यह आश्चर्य की बात नहीं है कि जंग इतनी धीमी है। किसी भी तरह से, दायर किए गए प्रदर्शन मुद्दे के योग्य दिखता है। –

उत्तर

6

इस मुद्दे के लिए एक फ़िक्स आज विलय कर दिया गया था। इसका मतलब है कि यह अगली रात का हिस्सा होना चाहिए, और जंग 1.3 में रिलीज होने की उम्मीद है। फिक्स ने Two-way substring search कार्यान्वयन को पुनर्जीवित किया कि जंग को मानक पुस्तकालय में नए Pattern API पर उपयोग और अनुकूलित किया गया था।

दो-तरफा एल्गोरिदम रस्ट के लिबकोर के लिए एक अच्छा मैच है क्योंकि यह एक रैखिक समय है जो खोज एल्गोरिदम है जो ओ (1) स्पेस का उपयोग करता है और उसे गतिशील आवंटन की आवश्यकता नहीं होती है।

विशेष कार्यान्वयन में एक साधारण जोड़ शामिल है जो इस विशेष प्रश्न को अत्यंत जल्दी से अस्वीकार कर देगा (और नहीं, यह इस प्रश्न के कारण लिखा नहीं गया था, यह पुराने कोड का भी हिस्सा था)।

सेटअप के दौरान खोजकर्ता सुई के लिए फिंगरप्रिंट का एक प्रकार की गणना करता है: सुई में प्रत्येक बाइट के लिए, अपनी कम 6 बिट है, जो एक संख्या 0-63 है लेते हैं, तो u64 चर byteset में इसी बिट निर्धारित किया है।

let byteset = needle.iter().fold(0, |a, &b| (1 << ((b & 0x3f) as usize)) | a); 

के बाद सुई केवल 'बी का होता है, byteset का मूल्य केवल 34 वीं बिट सेट (98 & 63 == 34) होगा।

अब हम किसी भी बाइट का परीक्षण कर सकते हैं चाहे वह सुई का हिस्सा हो या नहीं। यदि इसका संबंधित बिट byteset में सेट नहीं है, तो सुई मेल नहीं खा सकती है। प्रत्येक मामले में हम इस मामले में घास के मैदान में परीक्षण करेंगे 'ए' (97 & 63 == 33), और यह मेल नहीं खा सकता है। तो एल्गोरिदम एक बाइट पढ़ेगा, इसे अस्वीकार कर देगा, और फिर सुई की लंबाई को छोड़ देगा।

fn byteset_contains(&self, byte: u8) -> bool { 
    (self.byteset >> ((byte & 0x3f) as usize)) & 1 != 0 
} 

// Quickly skip by large portions unrelated to our substring 
if !self.byteset_contains(haystack[self.position + needle.len() - 1]) { 
    self.position += needle.len(); 
    continue 'search; 
} 

From libcore/str/pattern.rs in rust-lang/rust

+0

रूबी की तुलना में सुई और घास के दोनों यादृच्छिक डेटा थे, तो जंग का प्रदर्शन क्या होगा? क्या जंग के समग्र डिजाइन द्वारा उस मामले में कुछ हासिल किया जा सकता है? –

+0

मुझे लगता है कि दोनों को "aa .." क्वेरी में "bb .." से बहुत धीमी यादृच्छिक सुइयों की खोज करनी चाहिए। मुझे लगता है कि वे एक स्तर के खेल मैदान पर हैं। ध्यान दें कि जंग में नई स्ट्रिंग खोज अभी भी सीमा-सुरक्षित सुरक्षित जंग में लिखी गई है, और यह वैसे भी बहुत प्रतिस्पर्धी प्रतीत होता है। – bluss

+0

मुझे दिलचस्पी है यदि आप इस नए प्रत्यारोपण का उपयोग करते हुए जंग और रूबी के बीच नई प्रदर्शन तुलना करते हैं। – bluss

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