-
Notifications
You must be signed in to change notification settings - Fork 17
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Cache Scalafix instances globally #206
Conversation
c037bf0
to
7d57735
Compare
@bjaglin Do you mind reviewing it? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Just added some ideas based on my experience with sbt-scalafix. Next step would be to include the withToolClasspath
in the cache key, but the impact won't be as high/broad.
private val cache = new ConcurrentHashMap[(String, Seq[Repository]), SoftReference[Scalafix]] | ||
|
||
def getOrElseCreate(scalaVersion: String, repositories: Seq[Repository]) = | ||
cache.get((scalaVersion, repositories)) match { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having a blocking method like computeIfAbsent
would avoid getting several concurrent initialisations of the same instance on projects with many modules. This helped with sbt, not sure if the threading model is the same with mill.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a great idea!
I used compute
since I wanted to keep the SoftReference
.
|
||
private val cache = new ConcurrentHashMap[(String, Seq[Repository]), SoftReference[Scalafix]] | ||
|
||
def getOrElseCreate(scalaVersion: String, repositories: Seq[Repository]) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since repositories
is provided, should we have it in the cache key as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do, don't we?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops 🙈 my bad!
val scalafix = Scalafix | ||
.fetchAndClassloadInstance(scalaVersion, repositories.map(CoursierUtils.toApiRepository).asJava) | ||
val scalafix = ScalafixCache | ||
.getOrElseCreate(scalaVersion, repositories) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potential tweak even further: as I was mentioning no later than yesterday in the docs, only a major.minor version is required, so FWIW you could strip the patch version to maximize cache hit ratio (the instance will be the same for 3.3.3 and 3.3.4).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That assumption is true now but it might become false in future versions of scalafix. Since it's very rare to use different patch versions in the same build, I wouldn't bother trying to be clever here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Totally fair. FTR, that assumption is based on Scala current semver semantics ensuring backward and forward source compatibility for patch releases, but it could indeed change in the future.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alternatively, we could use the full scalafix classpath (as PathRef
s, either sorted or as Set
) as cache key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably ok, but nevertheless I'd like to point out that the cache is neither limited nor evicted. This could be an issue in a long running Mill session with frequently changing Scalafix instances. Unlikely but possible.
@lefou Maybe if I make it a |
Oh but |
@lolgab Yeah, a |
Fixes #175