Skip to content
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

Tweak reusable instances [ci: last-only] #8871

Merged
merged 2 commits into from
Apr 29, 2020
Merged

Conversation

som-snytt
Copy link
Contributor

Avoid some allocations if not enabled; and use factory methods.

Follow-up to the companion PR.

@som-snytt
Copy link
Contributor Author

I forgot to create as draft and also ci last-only.

There are 360 reusable instances in the scala build, mostly SymbolLookup, with the cache hit 400K times for SymbolLookup and 3.5M for FindMember.

Just a handful of reusages are deeper than 4, so the array is initially 4. SymbolLookup had 1 instance go to 9 (and reused a couple of times).

@SethTisue SethTisue marked this pull request as draft April 12, 2020 16:53
@som-snytt som-snytt changed the title Tweak reusable instances Tweak reusable instances [ci: last-only] Apr 13, 2020
diesalbla and others added 2 commits April 13, 2020 00:48
We modify ReusableInstance, so that instead of storing a single
instance in a mutable variable, we store a mutable stack (an
ArrayBuffer) of them.

Currently, when a reentrant call to the `using` method of
ReusableInstance occurs, a new object is allocated and discarded.
Using a stack allows us to keep any number of instances around,
so that the maximum number of allocated instances is the maximum
reentrant (recursion) stack depth.
Use factory methods, avoid needless allocations.
@som-snytt som-snytt marked this pull request as ready for review April 13, 2020 10:42
@som-snytt
Copy link
Contributor Author

Rebased with the cherry-picked commit.

private var taken = false
final class ReusableInstance[T <: AnyRef] private (make: => T, enabled: Boolean) {
private[this] val cache = if (enabled) new ArrayBuffer[T](ReusableInstance.InitialSize).tap(_.addOne(make)) else null
private[this] var taken = 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was going to complain that this would stymie inlining, but lo:

// make not private symbol accessed from inner classes, as well as
// symbols accessed from @inline methods
//
// See scala/bug#6552 for an example of why `sym.owner.enclMethod hasAnnotation ScalaInlineClass`
// is not suitable; if we make a method-local class non-private, it mangles outer pointer names.
def enclMethodIsInline = closestEnclMethod(currentOwner) hasAnnotation ScalaInlineClass
// scala/bug#8710 The extension method condition reflects our knowledge that a call to `new Meter(12).privateMethod`
//         with later be rewritten (in erasure) to `Meter.privateMethod$extension(12)`.
if ((currentClass != sym.owner || enclMethodIsInline) && !sym.isMethodWithExtension)
  sym.makeNotPrivate(sym.owner)

@som-snytt
Copy link
Contributor Author

If you stand diesalbla atop hrhino, they come up to retronym's shoulders, so I'm prepared to merge. Especially now that retronym is actually reusing the data reader.

@retronym
Copy link
Member

LGTM. ( that just autocorrected to “litmus”, which I liked. Is that the name of a test framework yet?)

I might circle back to this to make the maximum depth configurable. The classfile reader is pretty big and rarely reentrant, so a limit of 1 would make sense.

@retronym retronym merged commit e99c3fb into scala:2.13.x Apr 29, 2020
@SethTisue SethTisue added the performance the need for speed. usually compiler performance, sometimes runtime performance. label Apr 29, 2020
@som-snytt som-snytt deleted the review/8821 branch December 3, 2020 19:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
performance the need for speed. usually compiler performance, sometimes runtime performance.
Projects
None yet
6 participants