2009-05-01 14 views
13

मेरे पास एक पर्ल स्क्रिप्ट है जो बहुत सारे डेटा को क्रंच करती है। स्ट्रिंग वैरिएबल का एक गुच्छा है जो छोटे से शुरू होता है लेकिन डॉट (कॉन्सटेंटेशन) ऑपरेटर के बार-बार उपयोग के कारण वास्तव में लंबा हो जाता है। इस तरह से स्ट्रिंग को बढ़ाना परिणामस्वरूप बार-बार आवंटन होगा? यदि हां, तो स्ट्रिंग को पूर्व-आवंटित करने का कोई तरीका है?मैं पर्ल में एक स्ट्रिंग को पूर्व-आवंटित कैसे कर सकता हूं?

उत्तर

7

वैकल्पिक सुझाव जो कि आपके द्वारा किए जाने पर push स्ट्रिंग्स को एरे पर और join से निपटने के लिए बहुत आसान होगा।

+7

हालांकि सरणी में हर तत्व अपनी भूमि के ऊपर के सभी के साथ एक एसवी पैदा करता है। आप इस तरह से बहुत अधिक स्मृति का उपयोग करेंगे। –

-2

हां, पूर्व-विस्तारित तार जो आप जानते हैं, बढ़ना एक अच्छा विचार है।

आप ऐसा करने के लिए 'x' ऑपरेटर का उपयोग कर सकते हैं। उदाहरण के लिए, 1000 रिक्त स्थान preallocate रहे हैं:

$ s = "" x 1000:

+0

और उसके बाद असाइनमेंट के lhs पर substr का उपयोग करें। Uuuuugly। – chaos

+0

इस एक स्ट्रिंग 1000 रिक्त स्थान है, जब मैं तो कहते हैं कि "$ s = 'foo'" युक्त बनाने के करते हैं, मैं केवल पहले तीन इस्तेमाल किया के साथ एक 1000-चरित्र स्ट्रिंग मिल जाएगा या यह मुझे एक नया 3-चरित्र स्ट्रिंग दे देंगे और तुम्हारा दूर फेंक दो? (मैं बाद संदेह है, लेकिन वास्तव में नहीं जानता कि कैसे पर्ल यह संभाल लेंगे।) –

+1

आप पुन: असाइन करते हैं, तो यह पुरानी परिणाम फेंक होगा (यह करने के लिए संदर्भ दूर कल्पना करते हुए)। आपको केवल स्ट्रिंग प्रतिस्थापन करने की आवश्यकता होगी, जैसे डेव ने कहा, इसके कुछ हिस्सों को संशोधित करने के लिए। ++ सरणी-फिर-जुड़ें – Anonymous

7

पर्ल के तार, परिवर्तनशील हैं, इसलिए एक स्ट्रिंग को जोड़कर नहीं एक स्ट्रिंग दोहराव दंड देना है।

आप "तेज़" तरीके खोजने की कोशिश कर सकते हैं, लेकिन यह समयपूर्व अनुकूलन के लिए वास्तव में खराब है।

उदाहरण के लिए, मैंने एक कक्षा को मार दिया जो कड़ी मेहनत को दूर करता था। यह पूरी तरह से काम करता है, लेकिन यह है, इसकी सभी मूर्खतापूर्ण चाल के लिए, वास्तव में धीमा।

  Rate magic normal 
magic 1.72/s  -- -93% 
normal 23.9/s 1289%  -- 

हाँ, यह सही है, पर्ल 1200% मैं क्या सोचा था एक सम्मानजनक कार्यान्वयन था की तुलना में तेजी है:

यहाँ परिणाम है।

अपना कोड प्रोफाइल करें और वास्तविक समस्याएं ढूंढें, उन चीज़ों को अनुकूलित करने का प्रयास न करें जो ज्ञात समस्या भी नहीं हैं।

#!/usr/bin/perl 

use strict; 
use warnings; 

{ 

    package MagicString; 
    use Moose; 

    has _buffer => (
     isa => 'Str', 
     is => 'rw', 
    ); 
    has _buffer_size => (
     isa  => 'Int', 
     is  => 'rw', 
     default => 0, 
    ); 
    has step_size => (
     isa  => 'Int', 
     is  => 'rw', 
     default => 32768, 
    ); 
    has _tail_pos => (
     isa  => 'Int', 
     is  => 'rw', 
     default => 0, 
    ); 

    sub BUILD { 
     my $self = shift; 
     $self->_buffer(chr(0) x $self->step_size); 
    } 

    sub value { 
     my $self = shift; 
     return substr($self->{buffer}, 0, $self->{_tail_pos}); 
    } 

    sub append { 
     my $self = shift; 
     my $value = shift; 
     my $L  = length($value); 
     if (($self->{_tail_pos} + $L) > $self->{_buffer_size }){ 
      $self->{buffer} .= (chr(0) x $self->{step_size}); 
      $self->{_buffer_size} += $self->{step_size}; 
     } 
     substr($self->{buffer}, $self->{_tail_pos}, $L, $value); 
     $self->{_tail_pos} += $L; 
    } 
    __PACKAGE__->meta->make_immutable; 
} 


use Benchmark qw(:all :hireswallclock); 

cmpthese(-10 , { 
     magic => sub{ 
      my $x = MagicString->new(); 
      for (1 .. 200001){ 
       $x->append("hello"); 
      } 
      my $y = $x->value(); 
     }, 
     normal =>sub{ 
      my $x = ''; 
      for (1 .. 200001){ 
       $x .= 'hello'; 
      } 
      my $y = $x; 
     } 
    }); 
#use Data::Dumper; 
#print Dumper(length($x->value())); 
+3

कह रहा है कि पर्ल डुप्लिकेट नहीं करता है स्ट्रिंग केवल आधा सच है। पर्ल एक स्ट्रिंग के लिए अतिरिक्त कुछ अक्षर आवंटित करता है, इसलिए पर्ल सबसे अधिक संभावना है कि प्लगिंग को जोड़ते समय स्ट्रिंग युक्त मेमोरी बढ़े। इससे स्मृति की प्रतिलिपि हो सकती है। लेकिन यह आपके सिस्टम के मेमोरी मैनेजर में होता है जो बहुत तेज़ है। याद रखें, ओ (एन) गणित वर्ग में ओ (लॉग) को हरा देगा, लेकिन असली दुनिया में एल्गोरिदम के निरंतर समय मायने रखता है। सी तेज है। – Schwern

+0

दरअसल, ओ (1) बहुत अच्छा नहीं है अगर ओ (1) एक चरण के लिए कई दिन है, जबकि ओ (एन^2) केवल सेकंड ले सकता है :) हालांकि, यदि आपका डेटा आकार इतना बड़ा है तो शायद एक फायदा कि ओ (एन^2) दृष्टिकोण कई हफ्तों से अधिक है और आकार डेटा सेट सामान्य है। –

15

हां, एक स्ट्रिंग बढ़ने पर पर्ल दोहराए जाने वाले पुनरावृत्ति के परिणामस्वरूप होगा। पर्ल तारों के लिए थोड़ी सी अतिरिक्त जगह आवंटित करता है, लेकिन केवल कुछ बाइट्स। आप इसे डेवेल :: पीक का उपयोग करके देख सकते हैं। यह पुनर्वितरण बहुत तेज़ है और अक्सर वास्तव में स्मृति की प्रतिलिपि नहीं करता है। अपने मेमोरी मैनेजर पर भरोसा करें, यही कारण है कि आप पर्ल में प्रोग्रामिंग कर रहे हैं और सी नहीं। पहले इसे बेंचमार्क करें!

आप $#array = $num_entries के साथ सरणी को पूर्ववत कर सकते हैं और keys %hash = $num_keys के साथ हैश लेकिन length $string = $strlen काम नहीं करता है। यहां एक clever trick I dug up on Perlmonks है।

my $str = ""; 
vec($str, $length, 8)=0; 
$str = ""; 

या यदि आप एक्सएस में जाना चाहते हैं तो आप SvGROW() पर कॉल कर सकते हैं।

अराजकता का उपयोग करने के लिए अराजकता का सुझाव और उसके बाद सभी में शामिल होने से स्मृति को दोगुनी से अधिक का उपयोग किया जाएगा। सरणी के लिए मेमोरी। सरणी में प्रत्येक तत्व के लिए आवंटित प्रत्येक स्केलर के लिए मेमोरी। प्रत्येक स्केलर तत्व में आयोजित स्ट्रिंग के लिए मेमोरी। शामिल होने पर प्रतिलिपि के लिए स्मृति। यदि यह सरल कोड में परिणाम देता है, तो ऐसा करें, लेकिन ऐसा नहीं लगता कि आप किसी भी स्मृति को सहेज रहे हैं।

0

मैं जाना होगा सरणी/जिस तरह से शामिल होने:

push(@array, $crunched_bit) 

और फिर $str = join('', @array), ज्यादा कुछ नहीं, कुछ बाद में डीबगिंग के लिए सभी तत्वों का उपयोग करने की है।

+0

यह अतिरिक्त मेमोरी का उपयोग करेगा क्योंकि प्रत्येक सरणी तत्व को एक नया एसवी चाहिए। –

3

मैं विशेष रूप से पता नहीं कैसे पर्ल तार लागू किया जाता है, लेकिन एक बहुत अच्छी अनुमान है कि यह constant amortized time है। इसका मतलब यह है कि भले ही आप के लिए एक रास्ता खोजने के कर पूर्व आवंटित अपने स्ट्रिंग संभावना है कि संयुक्त समय यह सब स्क्रिप्ट के उपयोगकर्ताओं के लिए बचत होगी बार जब आप स्टैक ओवरफ़्लो पर this question पूछ खर्च से भी कम हो जाएगा।

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

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