I am using Revise.jl to work on a package for my research, and am noticing that “revising” a file to identical code with different variable names causes a function to stop allocating.
I am not sure how many details others will need to help me diagnose the issue, but my workflow is as follows:
- Run a script using Julia and the
-i
flag.startup.jl
consists only ofusing Revise
. - The script loads some data files, as well as BenchmarkTools.jl and Plots.jl
- Benchmark some functions that need to be allocation-free (for performance reasons).
The offending function is:
function is_cell_contained_by(cell1, poly)
cell_poly = cell_boundary_polygon(cell1) # this is an SVector
return all(edge_starts(cell_poly)) do pt # edge_starts returns an SVector
return PlanePolygons.point_inside_strict(poly, pt) # this does not allocate
end
end
And benchmarking it:
julia> @benchmark Euler2D.is_cell_contained_by($test_cell, $test_poly)
BenchmarkTools.Trial: 10000 samples with 709 evaluations per sample.
Range (min … max): 180.385 ns … 51.612 μs ┊ GC (min … max): 0.00% … 99.40%
Time (median): 194.587 ns ┊ GC (median): 0.00%
Time (mean ± σ): 237.031 ns ± 556.060 ns ┊ GC (mean ± σ): 8.90% ± 8.09%
▃▇█▅▄▁ ▂▂▂▃▃▂▂▁▁ ▂
███████████▇▇▆▆▆▆▄▃▅▃▁▁▄▄▁▄▁▃▄▁▁▁▇██████████▇▆▆▃▄▃▁▁▁▃▄▁▃▃▄▃▄ █
180 ns Histogram: log(frequency) by time 437 ns <
Memory estimate: 464 bytes, allocs estimate: 5.
Well, that’s odd. Edit the file defining is_cell_contained_by(...)
and let Revise.jl do its magic. I change the function to:
function is_cell_contained_by(cell1, poly)
cell_polys = cell_boundary_polygon(cell1)
return all(edge_starts(cell_polys)) do pt
return PlanePolygons.point_inside_strict(poly, pt)
end
end
Notice that only the variable name has changed: cell_poly
→ cell_polys
. Benchmark it again:
julia> @benchmark Euler2D.is_cell_contained_by($test_cell, $test_poly)
BenchmarkTools.Trial: 10000 samples with 985 evaluations per sample.
Range (min … max): 53.646 ns … 108.297 ns ┊ GC (min … max): 0.00% … 0.00%
Time (median): 57.632 ns ┊ GC (median): 0.00%
Time (mean ± σ): 57.934 ns ± 2.129 ns ┊ GC (mean ± σ): 0.00% ± 0.00%
▂▁▁▁▄▆█▇▇▅▁▁ ▁ ▁▁▂▁ ▁▁ ▂▁ ▂
▄█▆▇▃▃▁▁▁▆▇▃▅▇▅▇█████████████████▆▆▅▄▆▇███████████▇▆▆▆▅▄▅▆▆▆ █
53.6 ns Histogram: log(frequency) by time 63.8 ns <
Memory estimate: 0 bytes, allocs estimate: 0.
This is the behavior I expect… but I do not know why I have to force Revise.jl to pick up on the new function every time I run the script.
Is there a cache I can clear somewhere? Should I kill every running Julia process on my machine and try again? I am absolutely baffled, and I hope that I’m just falling into a common Revise.jl trap, rather than doing something truly stupid.