@@ -310,7 +310,122 @@ the amount of memory allocated by each line of code.
310310
311311# ## Line-by-Line Allocation Tracking
312312
313- To measure allocation line- by- line, start Julia with the ` --track-allocation=<setting>` command- line
313+ While [` @time` ](@ref ) logs high- level stats about memory usage and garbage collection over the course
314+ of evaluating an expression, it can be useful to log each garbage collection event, to get an
315+ intuitive sense of how often the garbage collector is running, how long it' s running each time,
316+ and how much garbage it collects each time. This can be enabled with
317+ [` GC.enable_logging(true)` ](@ref ), which causes Julia to log to stderr every time
318+ a garbage collection happens.
319+
320+ # ## [Allocation Profiler](@id allocation-profiler)
321+
322+ ! !! compat " Julia 1.8"
323+ This functionality requires at least Julia 1.8 .
324+
325+ The allocation profiler records the stack trace, type, and size of each
326+ allocation while it is running. It can be invoked with
327+ [` Profile.Allocs.@profile` ](@ref ).
328+
329+ This information about the allocations is returned as an array of ` Alloc`
330+ objects, wrapped in an ` AllocResults` object. The best way to visualize these is
331+ currently with the [PProf. jl](https: // github. com/ JuliaPerf/ PProf. jl) and
332+ [ProfileCanvas. jl](https: // github. com/ pfitzseb/ ProfileCanvas. jl) packages, which
333+ can visualize the call stacks which are making the most allocations.
334+
335+ The allocation profiler does have significant overhead, so a ` sample_rate`
336+ argument can be passed to speed it up by making it skip some allocations.
337+ Passing ` sample_rate=1.0` will make it record everything (which is slow);
338+ ` sample_rate=0.1` will record only 10 % of the allocations (faster), etc.
339+
340+ ! !! compat " Julia 1.11"
341+
342+ Older versions of Julia could not capture types in all cases. In older versions of
343+ Julia, if you see an allocation of type ` Profile.Allocs.UnknownType` , it means that
344+ the profiler doesn' t know what type of object was allocated. This mainly happened when
345+ the allocation was coming from generated code produced by the compiler. See
346+ [issue # 43688](https://github.com/JuliaLang/julia/issues/43688) for more info.
347+
348+ Since Julia 1.11 , all allocations should have a type reported.
349+
350+ For more details on how to use this tool, please see the following talk from JuliaCon 2022 :
351+ https: // www. youtube. com/ watch?v= BFvpwC8hEWQ
352+
353+ # #### Allocation Profiler Example
354+
355+ In this simple example, we use PProf to visualize the alloc profile. You could use another
356+ visualization tool instead. We collect the profile (specifying a sample rate), then we visualize it.
357+ ``` julia
358+ using Profile, PProf
359+ Profile.Allocs.clear()
360+ Profile.Allocs.@profile sample_rate=0.0001 my_function()
361+ PProf.Allocs.pprof()
362+ ```
363+
364+ Here is a more in- depth example, showing how we can tune the sample rate. A
365+ good number of samples to aim for is around 1 - 10 thousand. Too many, and the
366+ profile visualizer can get overwhelmed, and profiling will be slow. Too few,
367+ and you don' t have a representative sample.
368+
369+
370+ ``` julia-repl
371+ julia> import Profile
372+
373+ julia> @time my_function() # Estimate allocations from a (second-run) of the function
374+ 0.110018 seconds (1.50 M allocations: 58.725 MiB, 17.17% gc time)
375+ 500000
376+
377+ julia> Profile.Allocs.clear()
378+
379+ julia> Profile.Allocs.@profile sample_rate=0.001 begin # 1.5 M * 0.001 = ~1.5K allocs.
380+ my_function()
381+ end
382+ 500000
383+
384+ julia> prof = Profile.Allocs.fetch(); # If you want, you can also manually inspect the results.
385+
386+ julia> length(prof.allocs) # Confirm we have expected number of allocations.
387+ 1515
388+
389+ julia> using PProf # Now, visualize with an external tool, like PProf or ProfileCanvas.
390+
391+ julia> PProf.Allocs.pprof(prof; from_c=false) # You can optionally pass in a previously fetched profile result.
392+ Analyzing 1515 allocation samples... 100%|████████████████████████████████| Time: 0:00:00
393+ Main binary filename not available.
394+ Serving web UI on http://localhost:62261
395+ "alloc-profile.pb.gz"
396+ ```
397+ Then you can view the profile by navigating to http: // localhost: 62261 , and the profile is saved to disk.
398+ See PProf package for more options.
399+
400+ # #### Allocation Profiling Tips
401+
402+ As stated above, aim for around 1 - 10 thousand samples in your profile.
403+
404+ Note that we are uniformly sampling in the space of _all allocations_, and are not weighting
405+ our samples by the size of the allocation. So a given allocation profile may not give a
406+ representative profile of where most bytes are allocated in your program, unless you had set
407+ ` sample_rate=1` .
408+
409+ Allocations can come from users directly constructing objects, but can also come from inside
410+ the runtime or be inserted into compiled code to handle type instability. Looking at the
411+ " source code" view can be helpful to isolate them, and then other external tools such as
412+ [` Cthulhu.jl` ](https: // github. com/ JuliaDebug/ Cthulhu. jl) can be useful for identifying the
413+ cause of the allocation.
414+
415+ # #### Allocation Profile Visualization Tools
416+
417+ There are several profiling visualization tools now that can all display Allocation
418+ Profiles. Here is a small list of some of the main ones we know about:
419+ - [PProf. jl](https: // github. com/ JuliaPerf/ PProf. jl)
420+ - [ProfileCanvas. jl](https: // github. com/ pfitzseb/ ProfileCanvas. jl)
421+ - VSCode' s built- in profile visualizer (` @profview_allocs` ) [docs needed]
422+ - Viewing the results directly in the REPL
423+ - You can inspect the results in the REPL via [` Profile.Allocs.fetch()` ](@ref ), to view
424+ the stacktrace and type of each allocation.
425+
426+ # ### Line-by-Line Allocation Tracking
427+
428+ An alternative way to measure allocations is to start Julia with the ` --track-allocation=<setting>` command- line
314429option, for which you can choose ` none` (the default, do not measure allocation), ` user` (measure
315430memory allocation everywhere except Julia' s core code), or ` all` (measure memory allocation at
316431each line of Julia code). Allocation gets measured for each line of compiled code. When you quit
0 commit comments