Tuplicity: Macro-based Tuples

160 views
Skip to first unread message

Chris Hodapp

unread,
Apr 15, 2013, 9:54:55 PM4/15/13
to scala-l...@googlegroups.com
For a couple weeks, I've been investigating the potential to build a unified (and arity-unlimited) array-backed Tuple class using macros and the Dynamic trait, based on my original idea and the discussion that followed on
another scala-lang thread.

I've now written a starting-point implementation, which I've published on Github. I've implemented most of the important
part of the core Tuple interface, including Tuple creation, member access, stringification, and structural equality (and
the tests to show that they likely work right). There are still some significant features missing, however; I still need to
implement the 'copy' method and a way to convert to native Tuple types, for instance. I also plan to implement a mutable
version, which would pretty much be HArrays improved runtime performance.

In any case, my next goal is to put the code through a thorough round of microbenchmarking. To this end, I am soliciting
suggestions as to what sorts of benchmarks people would like to see and any obviously-poor implementation choices
that I've made (if you can read my code. If not, say so and I'll go into more detail).

Notes on expected (by me) performance: Performance is likely to be strongly affected by what types are present in the
tuple. Specifically, a Tuple where all members are of the same (primitive) type will likely be significantly faster than one
that contains a primitive and any reference type or 2+ primitive types. Reference-type members, however, should always
be fast to access (with the dubious case of a tuple containing a single reference being the fastest of all). It's actually a bit
more intricate than this and if someone wants to talk about the corner cases that I had to handle to make these things
behave properly with covariant type parameters, just let me know, and, once again, I would be happy to go into actual
detail on the implementation.

Chris Hodapp

unread,
May 2, 2013, 4:40:07 PM5/2/13
to scala-l...@googlegroups.com
Sorry for the long delay, everyone.

I have added some basic benchmarks with ScalaMeter.

The results seem quite promising (reformatted for easier reading):

cores: 8
jvm-name: Java HotSpot(TM) 64-Bit Server VM
jvm-vendor: Oracle Corporation
jvm-version: 23.7-b01
os-arch: x86_64
os-name: Mac OS X 

::Benchmark Native Tuple.apply(1,2,3)::
Parameters(repetitions -> 10): 0.216 

::Benchmark Tuplicity Tuple.apply(1,2,3)::
Parameters(repetitions -> 10): 0.15 

::Benchmark Native Tuple.apply(1,2,3,1.2)::
Parameters(repetitions -> 10): 0.253 

::Benchmark Tuplicity Tuple.apply(1,2,3,1.2)::
Parameters(repetitions -> 10): 0.157 

::Benchmark Native Tuple.apply(1,2,"x",3,1.2,"a")::
Parameters(repetitions -> 10): 0.26 

::Benchmark Tuplicity Tuple.apply(1,2,"x",3,1.2,"a")::
Parameters(repetitions -> 10): 0.155 

::Benchmark Native Tuple.apply(1,2,3)._1::
Parameters(repetitions -> 10): 0.272 

::Benchmark Tuplicity Tuple.apply(1,2,3)._1::
Parameters(repetitions -> 10): 0.151 

::Benchmark Native Tuple.apply(1,2,3,1.2)._1::
Parameters(repetitions -> 10): 0.311 

::Benchmark Tuplicity Tuple.apply(1,2,3,1.2)._1::
Parameters(repetitions -> 10): 0.219 

::Benchmark Native Tuple.apply(1,2,"x",3,1.2,"a")._1::
Parameters(repetitions -> 10): 0.313 

::Benchmark Tuplicity Tuple.apply(1,2,"x",3,1.2,"a")._1::
Parameters(repetitions -> 10): 0.219 

::Benchmark Native Tuple.apply(1,2,"x",3,1.2,"a")._3::
Parameters(repetitions -> 10): 0.268 

::Benchmark Tuplicity Tuple.apply(1,2,"x",3,1.2,"a")._3::
Parameters(repetitions -> 10): 0.115 

::Benchmark Native Tuple.apply(1,2,"x",3,1.2,("a": Any))._3::
Parameters(repetitions -> 10): 0.272 

::Benchmark Tuplicity Tuple.apply(1,2,"x",3,1.2,("a": Any))._3::
Parameters(repetitions -> 10): 0.12

Honestly, I never expected to get a performance gain of this magnitude. In fact, I was bracing for a slight loss in
performance (and thinking about ways to mitigate it). 

To this end, I thought of a way to make tuplicity.Tuple a value class, which should still be implemented in order to
further improve performance in the general case, at the expense of slowing down the (important) edge case where
a member has to be resolved at runtime.

I'm hoping for people to do the following:
1) Find major flaws in my methodology
2) Pull a fast, robust way to support heterogeneously typed arity-general pattern matching out of a hat

Chris Hodapp

unread,
May 2, 2013, 4:53:27 PM5/2/13
to scala-l...@googlegroups.com
As soon as I made my last post, I realized that I had messed up by making the tests non-orthogonal. I am redoing to remove the creation from the access tests.
Reply all
Reply to author
Forward
0 new messages