Some folks requested a few more benchmarks. In this case, I’m happy to oblige. Perl does not come off well in these benchmarks.
Perl Code
package class; sub new { return bless {}, $_[0]; } sub f1 { } sub f2 { my ($self, $x, $y) = @_; return ($x, $y); } sub f2a { my $self = shift; my $x = shift; my $y = shift; return ($x, $y); } package main; my $obj = class->new(); for ($i = 0; $i < 10_000_000; ++$i) { my ($x, $y) = $obj->f2(1, 2); }
Python Code
class myClass: def f1(self): pass def f2(self, a, b): return a, b x = myClass() for i in xrange (1, 10000000): a,b = x.f2('hello', 'world')
Perl Results
$ perl -v This is perl, v5.10.1 (*) built for i686-linux-thread-multi $ time perl ./func.pl # f1() real 0m5.052s user 0m5.044s sys 0m0.008s $ time perl ./func.pl # f2(1, 2)real 0m11.598s user 0m11.585s sys 0m0.000sreal 0m10.838s user 0m10.833s sys 0m0.000s $ time perl ./func.pl # f2a(1, 2)real 0m10.740s user 0m10.713s sys 0m0.004sreal 0m12.014s user 0m11.993s sys 0m0.012s $ time perl ./func.pl # f2a('hello', 'world')real 0m16.524s user 0m16.505s sys 0m0.008sreal 0m16.521s user 0m16.489s sys 0m0.000s
Python Results
$ time python ./func.py # f1() real 0m3.840s user 0m3.828s sys 0m0.004s $ time python ./func.py # f2(1, 2)real 0m4.546s user 0m4.504s sys 0m0.040sreal 0m5.887s user 0m5.860s sys 0m0.016s $ time python ./func.py # f2('hello', 'world')real 0m4.548s user 0m4.540s sys 0m0.008sreal 0m5.907s user 0m5.904s sys 0m0.004s
You’re cheating.
1. what is the method “f2a” in Perl?
2. your class::f2 returns 3 (three values) with memory allocation for 3 variables. It should look like sub f2 { return @_[1,2] }
3. Perl has “for (1..9_999_999)” form of loop, it works faster and it’s more Perl-way.
4. in Perl “for” loop you allocating memory for 2 variables $x and $y, why? In Python you calling method f2 in void context
Your post is junk for dummies.
http://perldoc.perl.org/Benchmark.html
Try this.
Benchmarking idiomatic code isn’t wrong! But do it correctly with stats etc.
I love how people get so worked up over benchmarks. Python has explicit arguments at “compile” time, perl gets its arguments at runtime. Of course python is slightly faster… big deal.
Now to really piss perl people off and benchmark threads! 😉 That reminds me … another trick to squeeze out performance is to compile perl without threading.
@juster – I doubt benchmarking threads in perl against threads in python will end well for python, if done on a modern desktop processor (or better), and using a test program that actually does locking correctly.
The global interpreter lock in python means that only one thread can run at any time (like coroutines, or green threads), so all those extra cores in the modern processor are going to be idle…
The way threads are implemented in perl can lead to some interesting effects, but for a real concurrent system, it’s pretty simple.
I’ve tested such benchmark according my remarks:
xxx@yyy:/tmp> time python 1.py
real 0m4.912s
user 0m4.894s
sys 0m0.006s
xxx@yyy:/tmp> time perl 1.pl
real 0m5.620s
user 0m5.506s
sys 0m0.004s
with Perl code:
package class;
sub new {
bless {}, $_[0];
}
sub f1
{
}
sub f2
{
@_[1,2];
}
package main;
my $obj = class->new();
for (1..10_000_000) {
$obj->f2('hello', 'world');
}
P.S. With increasing complexity of the program, performance of python programs will greatly decrease.
P.P.S. Author of post, Perl is not for you, it requires a sharp mind and intellect (and knowledge of the syntax of course). Write your programs in python and everything will be fine. 😉
Notice that f2 and f2a aren’t equivalent.
f2a returns a single value, while f2 returns three values.
The corrected f2a would be:
sub f2a {
my $self = shift;
my $x = shift;
my $y = shift;
($self, $x, $y);
}
Also, you should rewrite your for loop as:
for $i ( 1 .. 10_000_00 ) { … }
(I just realised my comments are similar to another commenter, but I will submit it anyway.)
@zloyrusskiy –
2. How often do you write Perl subroutines without explicitly unpacking @_? Your version of f2 is disingenuous.
3. Don’t care.
4. Yep, got that wrong, sorry. Note (if you’re trying to improve your English/manners), Nilson pointed that my error with f2a much more nicely.
You rude git.
@Anonymous – I considered using Benchmark.pm, but I don’t know the Python equivalent. You’re right though, readers are probably more interested in intra-Perl comparison.
@Juster – I suspect proper parallelizable code on a multi-core system will make Perl threads look good in comparison to Python threads. And if you’re just trying to avoid blocking, why not use something like AnyEvent (or is that your point)?
@Nilson – Thanks – I’ll fix up f2a (and call the Python in a non-void context) and update the post.
@Jared
2. In such small tasks – always
3. If you don’t care, use “range” (not “xrange”) in python code
You guys don’t sound very confident about perl threads. kbenson says, “I doubt”… Jared says “I suspect” that threads are faster than python’s coroutines.
Checkout the mandelbrot or chameneos benchmark at the debian language shootout:
http://shootout.alioth.debian.org/u32q/perl.php
I’m not bashing perl, just perl “threads”. Use fork() or the Coro module (omg coroutines). Yes on a multi-core machine Coro still outperforms threads. Try it yourself… benchmark!
PS I agree using unnamed subroutine arguments is ridiculous.
@zloyrusskiy –
2. This isn’t a task – none of these subroutines do anything useful. Are you an imbecile or do you just play one on my blog?
3. Er, no.
@juster – I didn’t mention python coroutines, you did. You’re moving the goalposts.
Most of my code has to work on Win32 so Coro is not particularly useful to me and fork is built over threads in any case.
@jared
2. I know it, you – idiot. I am writing this because I think that doing the right thing.
3. Your benchmarks are meaningless with such attitude. You optimize python code and using bad written Perl code. WOW, it’s a very correct comparison.
Thanks for updating the results. I think it shows that list assignment instead of shifting arguments is indeed slightly faster (but maybe not enough to warrant a style-change recommendation?)
By the way, I just realized that Python is probably even faster with string arguments (when compared to Perl) because I think it uses immutable strings. Perl actually copies those strings every time when passing by value.
No worries Nilson. It was good to correct the errors, thanks for pointing them out.
I agree with you about list vs shifting (makes sense right? – shifting does more work)
And yes, your explanation of the python string advantage makes sense. It can just pass the references around.
Cheers
@juster –
Well, I didn’t see I was called out to actually compare Perl threading to Python until today, but I took the challenge.
http://yaketyhack.blogspot.com/2010/07/threading-perl-vs-python.html
I’ve done quite a log of threading in Perl, and am aware of it’s limitation. I said “I doubt” instead of “I know” because I think that’s the only responsible way to speak when referring to how threads perform in a language in general. There’s so many different ways to use them, and the different threading models will have different strengths and weaknesses for each.
Nice post kbenson. And the results are fairly close to what I would have expected too.
[…] More Subroutine Benchmarking […]