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 -~----------~----~----~----~------~----~------~--~---