ما الأداء الذي يمكن أن نتوقعه مع نضوج تطبيقات Perl 6؟
-
01-10-2019 - |
سؤال
في كل مرة أقوم بتنزيل نسخة جديدة من Rakudo Perl 6 ، قمت بتشغيل التعبير التالي فقط للحصول على فكرة عن أدائها الحالي:
say [+] 1 .. 100000;
وتزداد السرعات ، ولكن في كل مرة ، هناك تأخير ملحوظ (عدة ثوان) للحساب. على سبيل المقارنة ، يعود شيء من هذا القبيل في بيرل 5 (أو اللغات الأخرى المفسرة) على الفور تقريبًا:
use List::Util 'sum';
print sum(1 .. 100000), "\n";
أو في روبي (أيضًا تقريبًا تقريبًا):
(1 .. 100000).inject(0) {|sum,x| sum+x}
إعادة كتابة التعبير باعتباره perl6 loop
ينتهي الأمر بنسبة ضعف أسرع من تقليل النطاق ، لكنه لا يزال تأخيرًا ملحوظًا للغاية (أكثر من ثانية) للحساب البسيط:
my $sum;
loop (my $x = 1; $x <= 100000; $x++) {$sum += $x}
لذا فإن سؤالي هو ، ما هي جوانب تطبيق Perl6 التي تسبب مشكلات الأداء هذه؟ وهل يجب أن يتحسن هذا مع مرور الوقت ، أم أن هذا هو تأثير جانبي مؤسف لنموذج "كل شيء كائن" يستخدمه Perl6؟
وأخيرا ، ماذا عن loop
البناء أسرع من [+]
مشغل التخفيض؟ أعتقد أن الحلقة ستؤدي إلى مزيد من العمليات الإجمالية من التخفيض.
تعديل:
سأقبل كليهما mortiz
'رمل hobbs
إجابات إذا استطعت. أن كل شيء يتم التعامل معه كطريقة استدعاء أكثر مباشرة يجيب على سبب [+]
يجري بطيئًا ، بحيث يحصل عليه المرء.
المحلول
شيء آخر يجب أن تفهمه حول عدم التحسين هو أنه مركبة. يتم كتابة جزء كبير من Rakudo في بيرل 6. لذلك على سبيل المثال [+]
يتم تنفيذ المشغل بالطريقة Any.reduce
(دعا مع $expression
ضبط ل &infix:<+>
) ، والتي لها حلقة داخلية
for @.list {
@args.push($_);
if (@args == $arity) {
my $res = $expression.(@args[0], @args[1]);
@args = ($res);
}
}
وبعبارة أخرى ، فإن التنفيذ الخالص للتقليل ، والذي يديره راكودو في حد ذاته. لذلك ليس فقط الرمز الذي تستطيع نرى لا تحصل على تحسين ، الرمز الذي أنت لا راجع أن جعل تشغيل الرمز الخاص بك هو أيضًا عدم التحسين. حتى حالات +
المشغل هي في الواقع مكالمات طريقة ، لأنه على الرغم من +
مشغل على Num
يتم تنفيذها من قبل Parrot ، لا يوجد شيء بعد في Rakudo للاعتراف بأنك حصلت على اثنين Num
S وحسن مكالمة الطريقة ، لذلك هناك إرسال ديناميكي كامل قبل أن يجد Rakudo multi sub infix:<+>(Num $a, Num $b)
ويدرك أن كل ما يفعله حقًا هو رمز opcode "إضافة". إنه عذر معقول لكونه أبطأ 100-1000x من بيرل 5 :)
تحديث 8/23/2010
مزيد من المعلومات من جوناثان وورثينجتون على أنواع التغييرات التي يجب أن تحدث مع نموذج كائن Perl 6 (أو على الأقل مفهوم Rakudo له) لجعل الأمور سريعة مع الحفاظ على الطبيعة "كل شيء" في Perl 6.
تحديث 1/10/2019
بما أنني أستطيع أن أرى أن هذا لا يزال يحظى بالاهتمام ... على مر السنين ، حصلت Rakudo/Moarvm على JIT ، واضطراب ، وتخصص ديناميكي ، و طن من العمل من قبل العديد من الناس تحسين كل جزء من النظام. والنتيجة هي أن معظم مكالمات الطريقة يمكن "تجميعها" ولديها تكلفة وقت تشغيل ما يقرب من الصفر. يسجل Perl 6 مئات أو آلاف المرات بشكل أسرع على العديد من المعايير مما كانت عليه في عام 2010 ، وفي بعض الحالات يكون أسرع من Perl 5.
في حالة المشكلة المبلغ إلى 100000 الذي بدأه السؤال ، لا يزال Rakudo 2018.06 أبطأ قليلاً من Perl 5.26.2:
$ time perl -e 'use List::Util 'sum'; print sum(1 .. 100000), "\n";' >/dev/null
real 0m0.023s
user 0m0.015s
sys 0m0.008s
$ time perl6 -e 'say [+] 1 .. 100000;' >/dev/null
real 0m0.089s
user 0m0.107s
sys 0m0.022s
ولكن إذا قمنا بإطفاء تكلفة بدء التشغيل عن طريق تشغيل الكود 10000 مرة ، فإننا نرى قصة مختلفة:
$ time perl -e 'use List::Util 'sum'; for (1 .. 10000) { print sum(1 .. 100000), "\n"; }' > /dev/null
real 0m16.320s
user 0m16.317s
sys 0m0.004s
$ time perl6 -e 'for 1 .. 10000 { say [+] 1 .. 100000; }' >/dev/null
real 0m0.214s
user 0m0.245s
sys 0m0.021s
يستخدم Perl6 بضع مئات من المللي ثانية أكثر من Perl5 على بدء التشغيل والتجميع ، ولكنه يكتشف كيفية القيام بالتجميع الفعلي حوالي 70 مرة أسرع.
نصائح أخرى
هناك بالفعل أسباب مختلفة تجعل راكودو بطيئة للغاية.
السبب الأول وربما الأهم هو أن Rakudo لا يقوم بأي تحسينات حتى الآن. الأهداف الحالية هي استكشاف المزيد من الميزات الجديدة ، وأن تصبح أكثر قوة. كما تعلمون ، يقولون "أولاً اجعله يعمل ، ثم اجعله صحيحًا ، ثم اجعله سريعًا".
السبب الثاني هو أن Parrot لا يقدم أي مجموعة JIT حتى الآن ، ومجمع القمامة ليس الأسرع. هناك خطط لمرجم JIT ، ويعمل الناس عليه (تم تمزيق الخطاب السابق لأنه كان i386 فقط وكابوس الصيانة). هناك أيضًا أفكار حول نقل Rakudo إلى VMs الأخرى ، ولكن هذا بالتأكيد سوف ينتظر حتى بعد نهاية يوليو.
في النهاية ، لا يمكن لأحد أن يعرف حقًا مدى سرعة تطبيق Perl 6 الكامل والتحديد بشكل جيد حتى يكون لدينا واحد ، لكنني أتوقع أن يكون أفضل بكثير من الآن.
راجع للشغل القضية التي استشهدت بها [+] 1..$big_number
يمكن أن يتم تشغيله في O (1) ، لأن 1..$big_number
إرجاع نطاق ، وهو ما يمكن أن يكون قابلاً للتأثير. حتى تتمكن من استخدام صيغة مجموع ل [+] Range
قضية. مرة أخرى ، يمكن القيام بذلك ، لكن هذا لم يتم بعد.
بالتأكيد ليس بسبب كل شيء كائن, ، لأن هذا صحيح في عدد من اللغات الأخرى أيضًا (مثل روبي). لا يوجد سبب يجعل بيرل 6 أبطأ من اللغات الأخرى مثل بيرل 5 أو روبي ، ولكن الحقيقة هي أن راكودو ليست ناضجة مثل بيرل أو كربي. لم يكن هناك الكثير من التحسين للسرعة بعد.
بالنظر إلى أن حالة الاختبار الخاصة بك الآن الأمثل إلى س (1) خوارزمية يعود ذلك على الفور تقريبًا ، ويبدو أن هناك العديد من التحسينات في الأسبوع ؛
أتوقع تحسن الأداء في كل مكان.
$ perl6 -e 'say [+] 1..10**1000; say now - INIT now'
5000000000000000000000000000000000000000000000 ...
0.007447
حتى لو لم يكن ذلك مخصصًا للنطاقات ، فإنه لا يزال أسرع قليلاً مما كان عليه.
يقوم الآن بحساب الاختبار الخاص بك في أقل من خمس من الثانية.
$ perl6 -e 'say [+] (1..100000).list; say now - INIT now'
5000050000
0.13052975
لقد قدمت هذه إلى مسابقة اللغة فيف في ديسمبر 2008. wp.pugs.pl
هي ترجمة حرفية لمثال Perl 5 ، wp.rakudo.pl
هو أكثر من غيره. لديّ برنامجان لأن الاثنان ينفذان مجموعة فرعية مختلفة من المواصفات. بناء المعلومات عفا عليها الزمن في هذه الأثناء. المصادر:
#!/usr/bin/env pugs
# Pugs: <http://pugs.blogs.com/> <http://pugscode.org/>
# prerequisite: ghc-6.8.x, not 6.10.x
# svn co http://svn.pugscode.org/pugs/
# perl Makefile.PL
# make
# if build stops because of haskeline, do:
# $HOME/.cabal/bin/cabal update ; $HOME/.cabal/bin/cabal install haskeline
# learn more: <http://jnthn.net/papers/2008-tcpw-perl64danoob-slides.pdf>
my %words;
for =<> {
for .split {
%words{$_}++
}
}
for (sort { %words{$^b} <=> %words{$^a} }, %words.keys) {
say "$_ %words{$_}"
}
#!/usr/bin/env perl6
# Rakudo: <http://rakudo.org/> <http://www.parrot.org/download>
# svn co http://svn.perl.org/parrot/trunk parrot
# perl Configure.pl
# make perl6
# Solution contributed by Frank W. & Moritz Lenz
# <http://use.perl.org/~fw/journal/38055>
# learn more: <http://jnthn.net/papers/2008-tcpw-perl64danoob-slides.pdf>
my %words;
$*IN.lines.split(/\s+/).map: { %words{$_}++ };
for %words.pairs.sort: { $^b.value <=> $^a.value } -> $pair {
say $pair
}
كانت هذه هي النتائج في عام 2008:
$ time ./wp.pugs.pl < /usr/src/linux/COPYING > foo
real 0m2.529s
user 0m2.464s
sys 0m0.064s
$ time ./wp.rakudo.pl < /usr/src/linux/COPYING > foo
real 0m32.544s
user 0m1.920s
sys 0m0.248s
اليوم:
$ time ./wp.pugs.pl < /usr/src/linux/COPYING > foo
real 0m5.105s
user 0m4.898s
sys 0m0.096s
$ time ./wp.rakudo.pl < /usr/src/linux/COPYING > foo
Divide by zero
current instr.: '' pc -1 ((unknown file):-1)
Segmentation fault
real 0m3.236s
user 0m0.447s
sys 0m0.080s
الإضافات المتأخرة: تم التعامل مع الحادث في لماذا أحصل على "تقسيم على صفر" عندما أحاول تشغيل البرنامج النصي مع Rakudo؟. برنامج Rakudo غير فعال ، انظر التعليقات أدناه و http://justrakudoit.wordpress.com/2010/06/30/Rakudo-and-peed/.