Skip to content

Investigate performance regression due to fields phase #226

Closed
@retronym

Description

@retronym

I'm looking at the profiles before and after 19aea1a (fields). I see a bit more time is spent in uniquing types. Looking back up the stack, this points to more work in substitution <- type param instantation <- base type computation.

Looking at the old implementation of mixin (2.11.x link below), I see that it only adds mixed in members for classes currently being compiled and for classes from the classpath that are superclasses of something being compiled.

https://github.com/scala/scala/blob/81a67eeacc7d2622ee364a21203b227142e2043e/src/compiler/scala/tools/nsc/transform/Mixin.scala#L355-L359

The new fields phase, which takes over some of the work of mixin, instead updates the class decls of each and every class that has .info called after uncurry, which amounts to just about every class that is reference

I don't actually see much time spent in the fields info transform itself, but there may be a secondary effect of adding an extra entry in all the TypeHistory-s of all symbols (maybe CompoundType#baseTypeSeqCache has a reduced hit rate?) (edited)

The overall effect is in the order of a 10% in hot performance. Big enough to care, small enough to be hard to pinpoint, especially given how it is spread around the place.

image

Here are the profiles if anyone wants to have a look:
https://dl.dropboxusercontent.com/u/106552/hot-scalap-2.12.0-19aea1a-SNAPSHOT.jfr https://dl.dropboxusercontent.com/u/106552/hot-scalap-2.12.0-fdb3105-SNAPSHOT.jfr

(Open with Java Mission Control)

They were generated with http://github.com/retronym/scala-jmh-suite:

;set scalaVersion in compilation := "2.12.0-fdb3105-SNAPSHOT"; compilation/jmh:run -vEXTRA -f1 -jvmArgs -XX:+UnlockDiagnosticVMOptions -jvmArgs -XX:+DebugNonSafepoints HotScalacBenchmark -p _scalaVersion=2.12.0-fdb3105-SNAPSHOT -psource=scalap -jvmArgs -XX:+UnlockCommercialFeatures -jvmArgs -XX:+FlightRecorder -jvmArgs -XX:StartFlightRecording=duration=120s,name=profile,settings=profile,filename=target/hot-scalap-2.12.0-fdb3105-SNAPSHOT.jfr -jvmArgs -XX:FlightRecorderOptions=settings=/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/jfr/profile.jfc;set scalaVersion in compilation := "2.12.0-19aea1a-SNAPSHOT"; compilation/jmh:run -vEXTRA -f1 -jvmArgs -XX:+UnlockDiagnosticVMOptions -jvmArgs -XX:+DebugNonSafepoints HotScalacBenchmark -p _scalaVersion=2.12.0-19aea1a-SNAPSHOT -psource=scalap -jvmArgs -XX:+UnlockCommercialFeatures -jvmArgs -XX:+FlightRecorder -jvmArgs -XX:StartFlightRecording=duration=120s,name=profile,settings=profile,filename=target/2.12.0-19aea1a-SNAPSHOT.jfr -jvmArgs -XX:FlightRecorderOptions=settings=/Library/Java/JavaVirtualMachines/jdk1.8.0_91.jdk/Contents/Home/jre/lib/jfr/profile.jfc

My next steps will be to compare things like the size of the uniques cache, the hit ratio on baseTypeSeqCache, the number of asSeenFrom operations.

I could also try making Fields#transformInfo be a no-op for previously compiled symbols other than in specific cases (like the "appears in superclass chain" rule used in mixin.)

Another experiment would be to quantify the cost of adding an info-transforming compiler phase at the spot where fields currently is.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions