[Shootout-list] Re: Erlang Crisis! :-)
Einar Karttunen
ekarttun@cs.helsinki.fi
Mon, 14 Jun 2004 11:40:18 +0300
This is a MIME-formatted message. If you see this text it means that your
E-mail software does not support MIME-formatted messages.
--=_courier-3146-1087202419-0001-2
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
On 13.06 23:53, Brent A. Fulgham wrote:
> For some reason, Erlang has absolutely terrible performance on heapsort,
> statistical moments, and interestingly even the producer/consumer
> threads implementation (an area I would have expected to be strong).
>
> Can some smart Erlang developers comment on why things look so bad?
> I've seen real-world Erlang programs run with much better performance
> than I would expect from these benchmarks.
Erlang is a functional language, which means there is no mutation. In
real world apps this is rarely a problem, but it makes things quite
"interesting" with benchmarks like this.
setelement takes a tuple and produces a new tuple, so it is of course
much slower than anything using inplace mutation for large tuples.
In real situations this is not really an issue as the fundamental
model of programming is quite different. e.g. the erlang array
tests actually use an in-memory database which can be accessed
by multiple processes...
The producer/consumer just demonstrates the classic "why is a protocoll
with window size of 1 slow", phenomenon. It is still two times faster
than the C version using mutexes ;) With a 10 times larger N (1000000)
the erlang version is about ten times faster than C... (see the attached
file). Note that the cvs version has two tiny bugs which make it hang
(s/prodcon/prodcons in the spawn).
--- prodcons/prodcons.erlang 2004-06-14 10:07:10.000000000 +0300
+++ /home/e/shootout/orig/prodcons.erl 2004-06-14 11:24:06.000000000 +0300
@@ -33,8 +33,8 @@
main([Arg]) ->
N = list_to_integer(atom_to_list(Arg)),
- P = spawn(prodcon, producer, [N, 0, self()]), %% spawn producer thread
- C = spawn(prodcon, consumer, [N, 0, P, self()]), %% spawn consumer thread
+ P = spawn(prodcons, producer, [N, 0, self()]), %% spawn producer thread
+ C = spawn(prodcons, consumer, [N, 0, P, self()]), %% spawn consumer thread
receive {P, NP} -> ok end, %% wait on producer thread
receive {C, NC} -> ok end, %% wait on consumer thread
io:format("~s ~w ~s ~w~n", ["Produced:", NP, "Consumed:", NC]),
Erlang startup is quite slow because it initializes the virtual
machine for all kinds of operation and spawns multiple erlang
server processes. For fast startup there is stand alone erlang
which produces executables suitable for command line use, however
building sae is not trivial and most people use the binary
distribution if they have a need for it.
One could shave a little bit of the times by using erlexec directly
instead of the erl shell script. A much better speedup would result
from using a dedicated boot script, but I don't know whether that
would be fair. When starting the erlang runtime loads a boot script
and loads all modules specified there and starts servers as specified
there. The default boot file starts 30 processes and loads 100+
modules. Out of these the tests use < 5%.
btw hipe compile could use optimizing flags like most other
languages do...
e@rei:~/shootout/shootout/bench$ cvs diff -u Makefile.mb
Index: Makefile.mb
===================================================================
RCS file: /cvsroot/shootout/shootout/bench/Makefile.mb,v
retrieving revision 1.11
diff -u -r1.11 Makefile.mb
--- Makefile.mb 12 Jun 2004 16:19:43 -0000 1.11
+++ Makefile.mb 14 Jun 2004 07:31:24 -0000
@@ -132,7 +132,7 @@
%.hipe_run: $(MB_SRCDIR)/%.hipe $(ERLC)
-rm $(TEST).beam
cp $< $(TEST).erl
- $(ERLC) +native $(TEST).erl
+ $(ERLC) +native +"{hipe, [o3]}" $(TEST).erl
touch $@
########################################
- Einar Karttunen
--=_courier-3146-1087202419-0001-2
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="bench.txt"
e@rei:~/shootout/orig$ time erl -noinput -s prodcons main 1
Produced: 1 Consumed: 1
real 0m0.121s
user 0m0.110s
sys 0m0.010s
e@rei:~/shootout/orig$ time ./prodcons.gcc 1
1 1
real 0m0.002s
user 0m0.000s
sys 0m0.001s
e@rei:~/shootout/orig$ time erl -noinput -s prodcons main 100000
Produced: 100000 Consumed: 100000
real 0m0.178s
user 0m0.160s
sys 0m0.015s
e@rei:~/shootout/orig$ time ./prodcons.gcc 100000
100000 100000
real 0m0.516s
user 0m0.065s
sys 0m0.232s
e@rei:~/shootout/orig$ time erl -noinput -s prodcons main 1000000
Produced: 1000000 Consumed: 1000000
real 0m0.659s
user 0m0.640s
sys 0m0.016s
e@rei:~/shootout/orig$ time ./prodcons.gcc 1000000
1000000 1000000
real 0m4.537s
user 0m0.637s
sys 0m1.781s
e@rei:~/shootout/orig$
--=_courier-3146-1087202419-0001-2--