You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: blog/2020/05/invalidations.md
+15-15Lines changed: 15 additions & 15 deletions
Original file line number
Diff line number
Diff line change
@@ -18,9 +18,9 @@ These efforts have met with considerable success: the upcoming Julia 1.5 feels "
18
18
But the job of reducing latency is not over yet.
19
19
Recently I got interested in a specific source of this latency, and this blog post is a summary of some of what I've learned about the scope of this problem and opportunities for further improvement.
20
20
21
-
# Method invalidation: what is it and when does it happen?
21
+
##Method invalidation: what is it and when does it happen?
22
22
23
-
## An example: compilation in the presence of Union-splitting
23
+
###An example: compilation in the presence of Union-splitting
24
24
25
25
When Julia compiles a method for specific types, it saves the resulting code
26
26
so that it can be used by any caller.
@@ -128,7 +128,7 @@ end
128
128
129
129
This is [union-splitting], a performance optimization for cases where an object might be of one of several types.
130
130
131
-
## Triggering method invalidation
131
+
###Triggering method invalidation
132
132
133
133
One point in particular is worth noting: what's up with that final `f(x)::Int` call?
134
134
Didn't it already handle all the possibilities?
@@ -208,7 +208,7 @@ If `applyf` is performance-critical, you'll be very happy that Julia tries to gi
208
208
But this leaves the door open to invalidation, which means recompilation the next time you use `applyf`.
209
209
If method invalidation happens often, this might contribute to making Julia "feel" sluggish.
210
210
211
-
# How common is method invalidation?
211
+
##How common is method invalidation?
212
212
213
213
Unfortunately, method invalidation is pretty common.
214
214
First, let's get some baseline statistics.
@@ -239,7 +239,7 @@ You can see that key packages used by large portions of the Julia ecosystem inva
239
239
hundreds or thousands of MethodInstances, sometimes more than 10% of the total
240
240
number of MethodInstances present before loading the package.
241
241
242
-
# How serious is method invalidation?
242
+
##How serious is method invalidation?
243
243
244
244
The next time you want to call functionality that gets invalidated,
245
245
you have to wait for recompilation.
@@ -286,7 +286,7 @@ Loading time is somewhat increased by invalidation, but the cost of
286
286
first-time usage is typically larger. When possible, it's best to get
287
287
the invalidation out of the way before starting your work.
288
288
289
-
# Can and should this be fixed?
289
+
##Can and should this be fixed?
290
290
291
291
Invalidations affect latency on their own, but they also impact other potential strategies for reducing latency.
292
292
For example, julia creates "precompile" (`*.ji`) files to speed up package usage.
@@ -302,7 +302,7 @@ The real question is whether there are *unnecessary* invalidations,
302
302
or an unexploited strategy to limit their impact.
303
303
Determining the answer to that question requires that we develop an understanding the common reasons for the large number of invalidations listed in the table above.
304
304
305
-
# An analysis of the causes of invalidation
305
+
##An analysis of the causes of invalidation
306
306
307
307
This section relies on a recent [pull request to Julia][PRJulia] and
308
308
the [invalidations branch][PRSC] of [SnoopCompile].
@@ -313,7 +313,7 @@ execute them first.
313
313
As we analyze causes of invalidation, you'll note that in some cases we can begin to think about how they might be fixed.
314
314
However, we'll save more detailed recommendations for the final section.
315
315
316
-
## New methods with greater specificity
316
+
###New methods with greater specificity
317
317
318
318
It will be simplest to start with a case we already understand, the `applyf` example above. In a fresh Julia session,
319
319
@@ -354,7 +354,7 @@ Perhaps there is no real need to ever call `applyf` with a `Vector{Any}`;
354
354
perhaps you can fix one of its upstream callers to supply a concretely-type vector.
355
355
In some cases, though, you might really need to call `applyf` with a `Vector{Any}`, in which case the best choice is to accept this invalidation as necessary and move on.
356
356
357
-
## New methods with ambiguous specificity
357
+
###New methods with ambiguous specificity
358
358
359
359
Now let's try a real-world case, where the outcomes are more complex.
360
360
@@ -471,7 +471,7 @@ So we've discovered an easy place where a developer could do something to produc
471
471
You'll also notice one example where the new method is *less specific*.
472
472
It is not clear why such methods should be invalidating, and this may be a Julia bug.
473
473
474
-
## Partial specialization
474
+
###Partial specialization
475
475
476
476
If you try
477
477
@@ -533,7 +533,7 @@ So here we see that a technique that very successfully reduces latencies also ha
533
533
Fortunately, these cases of partial specialization also seem to count as ambiguities, and so if ambiguous matches are eliminated it should also solve partial specialization.
534
534
In the statistics below, we'll lump partial specialization in with ambiguity.
535
535
536
-
## Some summary statistics
536
+
###Some summary statistics
537
537
538
538
Let's go back to our table above, and augment it with "sources" of invalidation:
539
539
@@ -558,7 +558,7 @@ In general terms, the last two columns should probably be fixed by changes in ho
558
558
The good news is that these counts reveal that much will likely be fixed by "automated" means.
559
559
However, it appears that there will need to be a second round in which package developers inspect individual invalidations to determine what, if anything, can be done to remediate them.
560
560
561
-
# Fixing invalidations
561
+
##Fixing invalidations
562
562
563
563
You may have noticed that two packages, `Example` and `Revise`, trigger far fewer invalidations that the rest of the packages in our analysis.
564
564
`Example` is quite trivial, but `Revise` and its dependencies are quite large.
@@ -573,7 +573,7 @@ The success of this effort gives one hope that other packages too may one day ha
573
573
As stated above, there is reason to hope that most of the invalidations marked as "ambiguous" will be fixed by changes to Julia's compiler.
574
574
Here our focus is on those marked "more specific," since those are cases where it is hard to imagine a generic fix.
575
575
576
-
## Fixing a case of type-instability
576
+
###Fixing a case of type-instability
577
577
578
578
In engineering Julia and Revise to reduce invalidations, at least two cases were fixed by resolving a type-instability.
579
579
For example, one set of invalidations happened because `CodeTracking`, a dependency of Revise's, defines new methods for `Base.PkgId`.
@@ -603,7 +603,7 @@ The other case was similar: a call from `Pkg` of `keys` on an AbstractDict of un
603
603
(due to a higher `@nospecialize` call).
604
604
Replacing `keys(dct)` with `Base.KeySet(dct)` (which is the default consequence of calling `keys`) eliminated a very consequential invalidation, one that triggered seconds-long latencies in the next `Pkg` command after loading Revise.
605
605
606
-
## Redirecting call chains
606
+
###Redirecting call chains
607
607
608
608
Let's return to our FixedPointNumbers `reduce_empty` example above.
609
609
A little prodding as done above reveals that this corresponds to the definition
@@ -743,7 +743,7 @@ However, it's a bit uglier than the original;
743
743
perhaps a nicer approach would be to allow one to supply `init` as a keyword argument to `maximum` itself.
744
744
While this is not supported on Julia versions up through 1.5, it's a feature that seems to make sense, and this analysis suggests that it might also allow developers to make code more robust against certain kinds of invalidation.
745
745
746
-
# Summary
746
+
##Summary
747
747
748
748
Julia's remarkable flexibility and outstanding code-generation open many new horizons.
749
749
These advantages come with a few costs, and here we've explored one of them, method invalidation.
0 commit comments