Skip to content

Instantly share code, notes, and snippets.

@lrytz
Created December 7, 2018 15:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lrytz/900dcc6aba5479ae615098bb0d74b1ee to your computer and use it in GitHub Desktop.
Save lrytz/900dcc6aba5479ae615098bb0d74b1ee to your computer and use it in GitHub Desktop.
Ensure stepper / stream / accumulator / array conversions don't box
import com.google.monitoring.runtime.instrumentation.AllocationRecorder
import com.google.monitoring.runtime.instrumentation.Sampler
import scala.collection.convert._
import scala.collection.JavaConverters._
// download java-allocation-instrumenter-3.2.0.jar from here:
// http://repo1.maven.org/maven2/com/google/code/java-allocation-instrumenter/java-allocation-instrumenter/3.2.0/
// compile and run with
// build/quick/bin/scalac -cp java-allocation-instrumenter-3.2.0.jar Test.scala
// build/quick/bin/scala -J-javaagent:java-allocation-instrumenter-3.2.0.jar -cp .:java-allocation-instrumenter-3.2.0.jar Test
object IntegerSampler extends Sampler {
val exclude = List(
"com.google.monitoring"
)
def trace: String = (new Exception).getStackTrace.drop(3).take(15).map(e => " " + e.toString).mkString("\n")
def sampleAllocation(count: Int, desc: String, newObj: Object, size: Long): Unit = {
if (newObj.isInstanceOf[java.lang.Integer]) {
val t = trace
if (!exclude.exists(trace.contains)) {
println(s"$desc : $newObj")
println(t)
}
}
}
}
object Test {
def show(i: Int) = {
AllocationRecorder.removeSampler(IntegerSampler)
println(i)
AllocationRecorder.addSampler(IntegerSampler)
}
def show(a: AnyRef) = {
AllocationRecorder.removeSampler(IntegerSampler)
println(a)
AllocationRecorder.addSampler(IntegerSampler)
}
def main(args: Array[String]): Unit = {
val ia = Array(10001,10002,10003) // small Integers are cached
val ba = ia.map(_.toShort)
val bset = collection.immutable.BitSet(10001,10002,10003)
val iasq = collection.immutable.ArraySeq.unsafeWrapArray(Array(10001,10002,10003))
AllocationRecorder.addSampler(IntegerSampler)
println("start testing")
val iast = ia.stepper
var i = 0
while (iast.hasStep) if (i == 0) i += iast.nextStep() else i += iast.nextInt()
show(i)
i = 0
val bast = ba.stepper
while (bast.hasStep) if (i == 0) i += bast.nextStep() else i += bast.nextInt()
show(i)
show(ia.seqStream.sum()) // result is boxed and unboxed, that's ok
show(ia.parStream.toScala(Accumulator))
show(ba.stepper.seqStream.toScala(IntAccumulator))
// show(ba.stepper.parStream.toScala(Array)) // boxes and unboxes, but that's also for BitSet(1).to(Array)
show(ba.stepper.parStream.toArray)
show(ia.seqStream.toScala(Accumulator).toArray)
show(ia.seqStream.spliterator.stepper.to(Accumulator))
// boxes and unboxes. could add a special case in IntAccumulator.fromSpecific, but there's no
// simple way to iterate over all Ints of a BitSet without boxing them.
// show(bset.to(IntAccumulator).seqStream.toArray)
show(ia.to(Accumulator).toArray: Array[Int])
// TODO
// boxes because the IntIndexedSeqStepper calls underlying.apply, which boxes
// will be solved by having specific steppers for ArraySeq (which can use the array steppers)
// show(iasq.stepper.seqStream.spliterator.stepper.to(Accumulator))
// also boxes, same reason as above
// show(iasq.seqStream.toScala(Accumulator))
show(iasq.to(Accumulator))
// boxes: stepper.to has special cases for primitive accumulators, but not for other target
// collections. so it goes to ArraySeq.from
// show(ia.stepper.to(collection.immutable.ArraySeq))
// similar to above, the toScala extension method has special cases for accumulators to avoid
// boxing, but not for other target collections.
// show(ia.seqStream.toScala(collection.immutable.ArraySeq))
// IntAccumulator.to calls ArraySeq.fromw, which boxes. maybe could add special cases to
// IntAccumulator.to, currently there aren't any. but that method doesn't take an
// `AccumulatorFactoryInfo` implicit that would allow knowing the factory. the method is an
// override, so adding a parameter would make an overload, not sure if it would be picked.
// show(ia.to(Accumulator).to(collection.immutable.ArraySeq))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment