Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find out what implicit(s) are used in my scala code

Problem statement:

  • I read in multiple sources/articles that implicits drive up scala compilation time

  • I want to remove/reduce them to minimum possible to see what compilation time without them will look like (codebase is around 1000 files of various complexity based on scalaz & akka & slick)

  • I don't really know what kind of static analysis I can perform. Any liks/references to already existing tooling highly appreciated.

like image 603
Petro Semeniuk Avatar asked Jan 01 '18 23:01

Petro Semeniuk


1 Answers

It is true that implicits can degrade compilation speed, especially for code that uses them for type-level computations. It is definitely worth it to measure their impact. Unfortunately it can be difficult to track down the culprits. There are tools that can help though:

  • Run scalac with -Ystatistics:typer to see how many tree nodes are processed during type-checking. E.g. you can check the number of ApplyToImplicitArgs and ApplyImplicitView relative to the total (and maybe compare this to another code base).

  • There is currently an effort by the Scala Center to improve the status quo hosted at scalacenter/scalac-profiling. It includes an sbt plugin that should be able to give you an idea about implicit search times, but it's still in its infancy (not published yet at the time of writing). I haven't tested it myself but you can still give it a try.

  • You can also compile with -Xlog-implicits, pipe the output to a file and analyse the logs. It will show a message for each implicit candidate that was considered but failed, complete with source position, search type and reason for the failure. Such failed searches are expensive. You can write a simple script with your favourite scripting language (why not Scala?) to summarize the data and even plot it with some nice graphics.

Aside: How to resolve a specific implicit instance?

Just use reify and good ol' println debugging:

import scala.collection.SortedSet
import scala.reflect.runtime.universe._
println(showCode(reify { SortedSet(1,2,3) }.tree))
// => SortedSet.apply(1, 2, 3)(Ordering.Int)
like image 146
g.krastev Avatar answered Sep 20 '22 18:09

g.krastev