I think there may be a somewhat straightforward solution to improving
Clojure's performance when passing primitives between functions.
Here's my understanding of the problem:  The IFn interface is a series
of invoke method signatures that take a number of java.lang.Objects as
parameters and returns a java.lang.Object.  Primitives can't be passed
this way and it would be a silly explosion of code to create the
methods signatures in IFn that included primitives.  The performance
characteristcs of "boxing" primitives relies on the JVM's performance
of allocating and deallocating objects.

My analysis:  The JVM is awfully good at handling transient objects
like the ones used for boxing, but no matter how good it is, it's
always better if the work needn't be done in the first place.

Here's my notion (bordering on brain fart):  Clojure does its own
primitive boxing using one element arrays.  Each thread has a
dynamically growable threadlocal cache of one-element arrays for each
primitive that needs to pass through the stack.  At the call site, the
compiler generates code to "allocate" the one element array
threadlocal of the appropriate type and stuffs the primitive into the
array.  Since the array itself is a java.lang.Object, it can pass
through the IFn interface without a problem.  At the target site, it
gets a bit more tricky.  If the object is type-coerced to a primitive,
it's simply a matter of pulling the first (and only) element out of
the array.  If the object is treated as a java.lang.Number, Clojure
must create the correct java object on the fly.  I don't think this
logic is very hard, but I can see how it might get tricky and have
lots of cases depending on how the compiler is designed.

Once the threadlocal cache is of sufficient size (I *think* the
largest it ever needs to grow is the largest number of primitives in
any method signature), the boxing costs fall into two categories:  In
the case where the object is coerced to a primitive, no tax is placed
on the garbage collector.  The cost is obtaining an available
primitive array, stuffing the primtive into the array, reading the
primitive out of the array and putting the array back into the cache.
This should be substantially faster than standard Java boxing.  In the
case where the object is treated as a java.lang.Number, the cost is
obtaining an available primitive array, stuffing the primtive into the
array, constructing the appropriate object and returning the the array
to the cache.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clojure@googlegroups.com
Note that posts from new members are moderated - please be patient with your 
first post.
To unsubscribe from this group, send email to
clojure+unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to