ठीक है, मुझे एक रास्ता मिला है जो 30 गुना तेज है-हालांकि, तर्कसंगत रूप से, इसकी धोखाधड़ी। मैंने Benchmark.pm कोड को बेंचमार्क करने के लिए शामिल किया है, क्योंकि आप स्पष्ट रूप से इसके बारे में परिचित नहीं हैं।
बेंचमार्क है:
Rate Join Cheat
Join 83294/s -- -97%
Cheat 2580687/s 2998% --
और कोड। तीसरी लाइन के बाद, मुझे लगता है कि आप समझ जाएंगे कि क्यों अपने यकीनन धोखाधड़ी:
use v5.14;
use Benchmark qw(cmpthese);
use Inline 'C';
sub an_join {
my ($s1, $s2) = @_;
return (join '', sort split(//, $s1)) eq
(join '', sort split(//, $s2));
}
use constant {
STR1 => 'abcdefghijklm',
STR2 => 'abcdefghijkmm',
STR3 => 'abcdefghijkml',
};
cmpthese(
0,
{
'Join' => 'an_join(STR1, STR2); an_join(STR1, STR3)',
'Cheat' => 'an_cheat(STR1, STR2); an_cheat(STR1, STR3)',
});
__END__
__C__
int an_cheat(const char *a, const char *b) {
unsigned char vec_a[26], vec_b[26];
const char *p, *end;
memset(vec_a, 0, sizeof(vec_a));
memset(vec_b, 0, sizeof(vec_b));
end = a+strlen(a);
for (p = a; p < end; ++p)
if (*p >= 'a' && *p <= 'z')
++vec_a[(*p)-'a'];
end = b+strlen(b);
for (p = b; p < end; ++p)
if (*p >= 'a' && *p <= 'z')
++vec_b[(*p)-'a'];
return 0 == memcmp(vec_a, vec_b, sizeof(vec_a));
}
बेशक
, अपने धोखा है क्योंकि इसकी में नहीं लिखा पर्ल-अपने पर्ल संस्करण नहीं है में सी इसके अलावा, यह सीमाएँ हैं (केवल लोअरकेस ASCII वर्णों के साथ सबसे महत्वपूर्ण होने के साथ काम करता है-यह सब कुछ और अनदेखा करता है)। लेकिन अगर आपको वास्तव में गति की आवश्यकता है, तो आप इस तरह धोखाधड़ी का उपयोग कर सकते हैं।
संपादित करें:
लेटिन 1 सभी के लिए विस्तार (अच्छी तरह से, कच्चे 8 बिट अक्षर, वास्तव में)। साथ ही, मैंने पाया कि संकलक एक सरल लूप (बिना अंक अंकगणितीय) को अनुकूलित करने में कामयाब रहा है, और इसे पढ़ने में भी आसान है, इसलिए ... बेंचमार्क मुझे बताता है कि लोअरकेस-एएससीआईआईआई-केवल संस्करण लगभग 10% तेज है:
int an_cheat_l1b(const char *a, const char *b) {
unsigned char vec_a[UCHAR_MAX], vec_b[UCHAR_MAX];
size_t len, i;
memset(vec_a, 0, sizeof(vec_a));
memset(vec_b, 0, sizeof(vec_b));
len = strlen(a);
for (i = 0; i < len; ++i)
++vec_a[((const unsigned char *)(a))[i]];
len = strlen(b);
for (i = 0; i < len; ++i)
++vec_b[((const unsigned char *)(b))[i]];
return 0 == memcmp(vec_a, vec_b, sizeof(vec_a));
}
ध्यान दें कि सी संस्करण का लाभ बढ़ता है क्योंकि स्ट्रिंग लंबे समय तक हो जाती है- इसकी उम्मीद है, क्योंकि इसके Θ (एन) पर्ल संस्करण ओ (एन · लॉगन) के विपरीत है। इसके अलावा पूर्ण लैटिन 1 के लिए जुर्माना भी कम हो जाता है, जिसका अर्थ है कि जुर्माना शायद memcmp है।
सरणी तुलना के लिए दिलचस्प पढ़ना: http://stackoverflow.com/questions/1609467/in-perl-is-there-a-built-in-way-to-compare-two-arrays-for-equality – Mat
स्ट्रिंग लम्बाई की तुलना भी कर सकते हैं और स्ट्रिंग लम्बाई अलग-अलग हैं, स्ट्रिंग को सॉर्ट करने से बचने के लिए जो निश्चित रूप से एनाग्राम नहीं हैं। स्ट्रिंग्स के लिए जो समान लंबाई हैं, लंबाई की तुलना बहुत तेज है, विभाजित-क्रम-जुड़ने से कहीं अधिक तेज है, इसलिए कोई भी प्रदर्शन हिट नगण्य होगी। –
ठीक है, आप तुलनात्मक कार्य से छुटकारा पाने के द्वारा प्रदर्शन में सुधार कर सकते हैं-आपको इसकी आवश्यकता नहीं है: 'शामिल हों', सॉर्ट स्प्लिट (//, $ s1) '। – derobert