in reply to Re^4: rough approximation to pattern matching using local (Multi Subs)
in thread rough approximation to pattern matching using local
What penalty does it impose over two (or more), separate (differently named) subroutines?Ie. Is the syntactic sugar worth the implementation costs?
A simple test I thought might be useful:
my $t; sub a {}; sub b {}; multi sub c (1) {}; multi sub c (2) {}; for ^7 { my $iterations = ^10 ** $_; say $iterations.max ~ " calls"; $t = now; for ^$iterations { $_ %% 2 ?? a() !! b() }; say "regular: {now - $t}"; $t = now; for ^$iterations { c($_ %% 2 ?? 1 !! 2) }; say "multi: {now - $t}"; }
With a recent Rakudo on MoarVM:
1 calls regular: 0.00630924 multi: 0.0046663 10 calls regular: 0.00344620 multi: 0.00392575 100 calls regular: 0.0056468 multi: 0.0079017 1000 calls regular: 0.0238749 multi: 0.02800533 10000 calls regular: 0.0541161 multi: 0.287505 100000 calls regular: 0.43776129 multi: 2.39229575 1000000 calls regular: 4.45541020 multi: 24.2623499
Unfortunately the numbers are clearly pretty useless.
I hope to l follow up this upcoming week when I've got a better handle on how to usefully answer your question. I'm thinking I'll install perl6-bench which has robust logic for squeezing noise (startup, gc, etc.). out of results. Other than the noise in the numbers, perhaps you could confirm the basic benchmark I created is a reasonable test in principle to answer your question?
I believe the "benchmark" I used above caused confusion in this thread due to its inclusion of implicit `where` constraints (where the argument had the value 1 or 2). These literal fixed value `where` constraints are supposed to one day be resolvable at compile-time but as I write this (April 2015) they are resolved at run-time.
So here's an alternative "benchmark":
my $t; class A {}; class B {}; sub a (A $a) {}; sub b (B $a) {}; multi sub c (A $a) {}; multi sub c (B $a) {}; for ^7 { my $iterations = ^10 ** $_; say $iterations.max ~ " calls"; $t = now; for ^$iterations { $_ %% 2 ?? a(A) !! b(B) }; say "regular: {now - $t}"; $t = now; for ^$iterations { c($_ %% 2 ?? A !! B) }; say "multi: {now - $t}"; }
And the timing results:
1 calls regular: 0.00321471 multi: 0.00306454 10 calls regular: 0.0029107 multi: 0.0029139 100 calls regular: 0.0032379 multi: 0.00331093 1000 calls regular: 0.0091466 multi: 0.00742758 10000 calls regular: 0.04885046 multi: 0.053550 100000 calls regular: 0.5330036 multi: 0.5973669 1000000 calls regular: 5.6755910 multi: 5.946978
So, as I tried to explain in other comments in this thread, type checking and candidate ordering of multisub calls are generally completed at compile-time, just like regular subs.
»ö« . o O ( "the celebrity tell-all of the Perl-6 cult?" )
|
|---|