Created
September 13, 2013 13:09
-
-
Save jonifreeman/6550469 to your computer and use it in GitHub Desktop.
Record compilation performance
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Compilation time of each commented function on my machine (as repoted by sbt console). | |
// ********************************************************************** | |
// Test.scala | |
import shapeless._ | |
import syntax.singleton._ | |
object Test { | |
val r = | |
("k01" ->> 1) :: ("k02" ->> 1) :: ("k03" ->> 1) :: ("k04" ->> 1) :: ("k05" ->> 1) :: | |
("k06" ->> 1) :: ("k07" ->> 1) :: ("k08" ->> 1) :: ("k09" ->> 1) :: ("k10" ->> 1) :: | |
("k11" ->> 1) :: ("k12" ->> 1) :: ("k13" ->> 1) :: ("k14" ->> 1) :: ("k15" ->> 1) :: | |
("k16" ->> 1) :: ("k17" ->> 1) :: ("k18" ->> 1) :: ("k19" ->> 1) :: ("k20" ->> 1) :: | |
("k21" ->> 1) :: ("k22" ->> 1) :: ("k23" ->> 1) :: ("k24" ->> 1) :: ("k25" ->> 1) :: | |
("k26" ->> 1) :: ("k27" ->> 1) :: ("k28" ->> 1) :: ("k29" ->> 1) :: ("k30" ->> 1) :: | |
("k31" ->> 1) :: ("k32" ->> 1) :: ("k33" ->> 1) :: ("k34" ->> 1) :: ("k35" ->> 1) :: HNil | |
// r get "k01" // 1s | |
// r get "k02" // 4s | |
// r get "k03" // 7s | |
// r get "k04" // 10s | |
// r get "k05" // 12s | |
// r get "k10" // 21s | |
// r get "k20" // 30s | |
// This loops over every field: | |
// jsonless.json4s.toJSON(r) // 5s | |
// Cost of selecting with HList.select function is constant: | |
// val k02 = Witness("k02") | |
// r.select[record.FieldType[k02.T, Int]] // 37s | |
// val k20 = Witness("k20") | |
// r.select[record.FieldType[k20.T, Int]] // 37s | |
} | |
// Test2 compares to encoding which was used in sqltyped < 0.4.0. | |
// Here record is a HList of Tuple2s. Minimal implementation at the end of a gist. | |
// Compilation times were 3-4 times quicker. | |
// ********************************************************************** | |
// Test2.scala | |
import shapeless.HNil | |
import legacyrecord._ | |
object k01; object k02; object k03; object k04; object k05; object k06; object k07; object k08; | |
object k09; object k10; object k11; object k12; object k13; object k14; object k15; object k16; | |
object k17; object k18; object k19; object k20; object k21; object k22; object k23; object k24; | |
object k25; object k26; object k27; object k28; object k29; object k30; object k31; object k32; | |
object k33; object k34; object k35 | |
object Test2 { | |
val r = | |
(k01 -> 1) :: (k02 -> 1) :: (k03 -> 1) :: (k04 -> 1) :: (k05 -> 1) :: | |
(k06 -> 1) :: (k07 -> 1) :: (k08 -> 1) :: (k09 -> 1) :: (k10 -> 1) :: | |
(k11 -> 1) :: (k12 -> 1) :: (k13 -> 1) :: (k14 -> 1) :: (k15 -> 1) :: | |
(k16 -> 1) :: (k17 -> 1) :: (k18 -> 1) :: (k19 -> 1) :: (k20 -> 1) :: | |
(k21 -> 1) :: (k22 -> 1) :: (k23 -> 1) :: (k24 -> 1) :: (k25 -> 1) :: | |
(k26 -> 1) :: (k27 -> 1) :: (k28 -> 1) :: (k29 -> 1) :: (k30 -> 1) :: | |
(k31 -> 1) :: (k32 -> 1) :: (k33 -> 1) :: (k34 -> 1) :: (k35 -> 1) :: HNil | |
// r get k01 // 1s | |
// r get k02 // 2s | |
// r get k03 // 2s | |
// r get k04 // 3s | |
// r get k05 // 3s | |
// r get k10 // 5s | |
// r get k20 // 7s | |
} | |
// ********************************************************************** | |
// legacyrecord.scala | |
import shapeless._ | |
object legacyrecord { | |
implicit def recordOps[R <: HList](r: R): RecordOps[R] = new RecordOps(r) | |
} | |
final class RecordOps[R <: HList](r: R) { | |
def lookup[K](implicit lookup: Selector[R, K]): lookup.Out = lookup(r) | |
def get[K](k: K)(implicit lookup0: Selector[R, K]): lookup0.Out = lookup[K] | |
} | |
@annotation.implicitNotFound(msg = "No field ${K} in record ${L}") | |
trait Selector[L <: HList, K] { | |
type Out | |
def apply(l : L): Out | |
} | |
trait LowPrioritySelector { | |
type Aux[L <: HList, K, Out0] = Selector[L, K] { type Out = Out0 } | |
implicit def hlistSelect[H, T <: HList, K] | |
(implicit st : Selector[T, K]): Aux[H :: T, K, st.Out] = | |
new Selector[H :: T, K] { | |
type Out = st.Out | |
def apply(l : H :: T): Out = st(l.tail) | |
} | |
} | |
object Selector extends LowPrioritySelector { | |
implicit def hlistSelect1[K, V, T <: HList]: Aux[(K, V) :: T, K, V] = | |
new Selector[(K, V) :: T, K] { | |
type Out = V | |
def apply(l : (K, V) :: T): Out = l.head._2 | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment