primitive meta data

21 views
Skip to first unread message

Islon

unread,
Oct 14, 2008, 11:34:15 PM10/14/08
to clo...@googlegroups.com
Hi.

I've made a dumb (very dumb) performance comparison function just to play with the language.
I wanted to mark some symbols with a float primitive type but the compiler complained so I had to annotate it with the Float class.
Here is the function:

(defn dumb-test []
  (let [#^Float f2 567.09723]
    (loop [#^Float f 1.8, i 10000000]
      (if (zero? i)
        f
        (recur (/ f f2) (dec i))))))

And the test:

(loop [i 50]
  (time (dumb-test))
  (if (zero? i)
    i
    (recur (dec i))))

There's a way to put a float primitive type in the metadata to prevent the Float -> float unboxing?
Feel free to point some mistakes I probably made, I've just started learn clojure.

The clojure version took an average: "Elapsed time: 217.833342 msecs" in my machine.

The java version (below) took average 23 msecs:

private static float dumbTest() {
        float f = 1.8f;
        float f2 = 567.09723f;
        for(int i = 0; i < 10000000; i++) {
            f /= f2;
        }
        return f;
    }

Regards.
Islon

Parth Malwankar

unread,
Oct 15, 2008, 7:08:20 AM10/15/08
to Clojure
The following was somewhat faster.

(defn dumb-test []
(let [f2 (float 567.09723)]
(loop [f (float 1.2), i (long 10000000)]
(if (zero? i)
f
(recur (/ f f2) (dec i))))))

I get about 59ms on my machine.
user=> (time (dumb-test))
"Elapsed time: 59.245176 msecs"
0.0

Parth

Chouser

unread,
Oct 15, 2008, 11:04:25 AM10/15/08
to clo...@googlegroups.com
On Wed, Oct 15, 2008 at 7:08 AM, Parth Malwankar
<parth.m...@gmail.com> wrote:
>
> On Oct 15, 8:34 am, Islon <islonsche...@gmail.com> wrote:
>>
>> (defn dumb-test []
>> (let [#^Float f2 567.09723]
>> (loop [#^Float f 1.8, i 10000000]
>> (if (zero? i)
>> f
>> (recur (/ f f2) (dec i))))))

The type hints aren't really helping there, I think. #^Float might
help if you were calling a Java function and wanted to avoid the
runtime reflection lookup cost, but you're only calling Clojure
functions so it doesn't help.

On my machine, about 180 msecs

To get unboxed primitives, you have to do more like what Parth did:

> (defn dumb-test []
> (let [f2 (float 567.09723)]
> (loop [f (float 1.2), i (long 10000000)]
> (if (zero? i)
> f
> (recur (/ f f2) (dec i))))))

On my machine that's 48 msecs.

But we can do a bit better, just by using unchecked-dec:

(defn dumb-test []
(let [f2 (float 567.09723)]
(loop [f (float 1.2), i (long 10000000)]
(if (zero? i)
f

(recur (/ f f2) (unchecked-dec i))))))

That's 24 msecs for me.

But I don't know how useful these kinds of micro-benchmarks really
are. Clojure's "fast enough" so let's go solve some interesting
problems...

--Chouser

Islon

unread,
Oct 15, 2008, 11:35:27 AM10/15/08
to clo...@googlegroups.com
Thanks for the advices.
The unchecked version run as fast as java.
Before I go solve some interesting problem I have to learn the language ;)
Thanks anyway.

Rich Hickey

unread,
Oct 15, 2008, 11:42:47 AM10/15/08
to Clojure


On Oct 15, 11:04 am, Chouser <chou...@gmail.com> wrote:
> On Wed, Oct 15, 2008 at 7:08 AM, Parth Malwankar
>
Exactly. It's likely that that 24 msecs is the same time as the
original Java would be on your box. It's already been demonstrated
that with the -server JIT, Clojure can, in inner loops involving
primitives, equal the speed of Java. So everyone can rest assured that
that capability is there should they need it. The way to get it is as
you've demonstrated, with primitive casts. Type hints are only for
helping the compiler with Java method calls.

But until there's a real performance challenge that's the bottleneck
in a real application, there's no reason to get involved in this kind
of micro-optimization - it's really a waste of time.

Writing code in the clearest, most high-level way is best, and as you
say, in Clojure, is usually fast enough.

Rich
Reply all
Reply to author
Forward
0 new messages