Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

Re^2: Why is this code so much slower than the same algorithm in C?

by Joost (Canon)
on Dec 10, 2008 at 20:36 UTC ( [id://729499]=note: print w/replies, xml ) Need Help??


in reply to Re: Why is this code so much slower than the same algorithm in C?
in thread Why is this code so much slower than the same algorithm in C?

The abstractions in the language don't have to be a significant obstacle to performance. In fact, if the language provides the right abstractions, you can probably improve on most C implementations of an algorithm just by using some well-optimized built-in abstractions. Perl currently doesn't come very close to doing this, though it's relatively quick compared to the other popular dynamic "scripting" languages (Ruby, Python, PHP).

C-style "fixed" typing, especially when dealing with basic numeric types is still hard to beat for a language as dynamic as perl, but as you hinted, a good enough JIT compiler (like Java's) could get pretty close to (and in some cases probably beat) the speed of a C implementation.

A few existing dynamic languages that have good compilers (some need hinted with type declarations at the tight portions of code - which may be cheating, but good Common Lisp implementations use it, and AFAIK they don't even use a JIT compiler), can already come really close to C's speed.

As for performance in dynamic languages in general, I'll also drop a link to clojure here - it's a lisp (dynamic typing included) implemented in Java, which for speed is probably close to the top of dynamic languages and has very interesting multithreading/concurrency properties.

UPDATE It took some time to get it right; I'm new at clojure and the OP's program doesn't translate into idiomatic functional constructs (mainly because the OP's algorithm is stupidly inefficient) - but I've tried to keep it as close to the original constructs as possible:

(defn inner [i] (loop [j 1] (if (= 0 (rem i j)) (if (< j 20) (recur (+ 1 j)) i) nil))) (defn loops [] (loop [i 20] (let [result (inner i)] (if result (print (format "Number %d\n" result)) (recur (+ i 20)))))) (defn time-me [] (time (loops)))
Results:
(time-me) Number 232792560 "Elapsed time: 10865.715 msecs" nil
For comparison: this is on a 4 months old macbook, where the OPs perl code takes about 19 seconds (which includes compile time, but that's tiny in comparison to the total):
joost-diepenmaats-macbook:~ joost$ time perl test.pl Number: 232792560 real 0m19.568s user 0m19.078s sys 0m0.060s

updated again to convert tabs to spaces in pasted code, and again because the timing for the clojure code was way off due to stupid programmer syndrome My code is still way slow compared to the OP's reported C time, but about twice as fast as perl - not that bad for one of my first attempts at clojure.

Replies are listed 'Best First'.
Re^3: Why is this code so much slower than the same algorithm in C?
by LanX (Saint) on Dec 10, 2008 at 23:09 UTC
    > A few existing dynamic languages that have good compilers (some need hinted with type declarations at the tight portions of code - which may be cheating, but good Common Lisp implementations use it, and AFAIK they don't even use a JIT compiler), can already come really close to C's speed.

    thanx for the insight... well another good reason to overcome my parens-allergy ; )

    ... maybe starting with elisp.

    Cheers Rolf

    PS: I suppose the dynamic structure of lisp (data == code) enforces a late compiling (comparable to JIT) and therefore the potential to high optimization ...

      Actually the code = data does not particularly enforce late compiling - it just means you can have a more efficient means to a] talk to the compiler and b] pre-process code before it reaches the compiler (since you can process structured data instead of strings). Being able to talk to the compiler from running code at all (using eval for example) is of course a good reason to optimize for all kinds of compiling speed-ups.

      Anyway elisp is OK (if fairly slow), but it's quite archaic compared to scheme, common lisp and other "modern" lisps (basically any serious lisp created/standardized since the 80's). Most of the details are fairly easy to overcome, but the lack of true built-in support for lexical scoping (and closures) is probably the most annoying.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://729499]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (8)
As of 2024-04-16 09:58 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found