From 6164aa6bcfc9a37cc8ebd31dbbe4e0654288785d Mon Sep 17 00:00:00 2001 From: Tim Holy Date: Wed, 27 Oct 2021 09:39:04 -0500 Subject: [PATCH] Add warntype_last (fixing inference probs.) (#175) After left-clicking on a bar, you can call `warntype_last()` from the REPL and see the results of `code_warntype` for the bar you clicked on. --- Project.toml | 2 ++ README.md | 23 +++++++++++++++++++++-- src/ProfileView.jl | 13 ++++++++++++- test/runtests.jl | 14 ++++++++++++++ 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/Project.toml b/Project.toml index e809aea..8e607f1 100644 --- a/Project.toml +++ b/Project.toml @@ -13,6 +13,7 @@ Gtk = "4c0ca9eb-093a-5379-98c5-f87ac0bbbf44" GtkReactive = "27996c0f-39cd-5cc1-a27a-05f136f946b6" InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240" IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" +MethodAnalysis = "85b6ec6f-f7df-4429-9514-a64bcd9ee824" Profile = "9abbd945-dff8-562f-b5e8-e1ebf5ef1b79" UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" @@ -25,6 +26,7 @@ Graphics = "0.4, 1" Gtk = "0.18, 1" GtkReactive = "0.7, 1" IntervalSets = "0.2, 0.3, 0.4, 0.5" +MethodAnalysis = "0.4" julia = "1" [extras] diff --git a/README.md b/README.md index 4f54a3b..5cc4341 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ # Introduction -This package contains tools for visualizing profiling data collected +This package contains tools for visualizing and interacting with profiling data collected with [Julia's][Julia] built-in sampling [profiler][Profiling]. It can be helpful for getting a big-picture overview of the major @@ -19,6 +19,13 @@ This type of plot is known as a [flame graph](https://github.com/brendangregg/FlameGraph). The main logic is handled by the [FlameGraphs][FlameGraphs] package; this package is just a visualization front-end. +Compared to other flamegraph viewers, ProfileView adds a number of additional useful interactivity features, such as: + +- left-clicking to take you to the source code for a particular statement +- analyzing inference problems via `code_warntype` for calls that may be deep in your call chain. + +These features are described in detail below. + ## Installation Within Julia, use the [package manager][pkg]: @@ -27,7 +34,7 @@ using Pkg Pkg.add("ProfileView") ``` -## Usage and visual interpretation +## Tutorial: usage and visual interpretation To demonstrate ProfileView, first we have to collect some profiling data. Here's a simple test function for demonstration: @@ -111,6 +118,15 @@ from the absence of pastel-colored bars above much of the red, we might guess that this makes a substantial contribution to its total run time. +To determine the nature of the inference problem(s) in a red bar, left-click on it +and then enter + +```julia +julia> warntype_last() +``` + +at the REPL. You'll see the result of Julia's `code_warntype` for that particular call. + ## GUI features ### Gtk Interface @@ -140,6 +156,9 @@ contribution to its total run time. window, which you can populate with saved data by clicking on the "open" icon. +- After clicking on a bar, you can type `warntype_last` and see the + result of `code_warntype` for the call represented by that bar. + **NOTE**: ProfileView does not support the old JLD-based `*.jlprof` files anymore. Use the format provided by FlameGraphs v0.2 and higher. diff --git a/src/ProfileView.jl b/src/ProfileView.jl index 66cfe04..497b979 100644 --- a/src/ProfileView.jl +++ b/src/ProfileView.jl @@ -7,6 +7,7 @@ end using Profile using FlameGraphs using Base.StackTraces: StackFrame +using MethodAnalysis using InteractiveUtils using Gtk.ShortNames, GtkReactive, Colors, FileIO, IntervalSets import Cairo @@ -15,10 +16,20 @@ using Graphics using FlameGraphs: Node, NodeData using Gtk.GConstants.GdkModifierType: SHIFT, CONTROL, MOD1 -export @profview +export @profview, warntype_last const clicked = Ref{Any}(nothing) # for getting access to the clicked bar +""" + warntype_last() + warntype_last(io::IO; kwargs...) + +Show `code_warntype` for the most recently-clicked bar. + +Optionally direct output to stream `io`. Keyword arguments are passed to `code_warntype`. +""" +warntype_last(io::IO=stdout; kwargs...) = code_warntype(io, call_type(ProfileView.clicked[].linfo.specTypes)...; kwargs...) + svgwrite(args...; kwargs...) = error("SVG support has moved to the ProfileSVG package") mutable struct ZoomCanvas diff --git a/test/runtests.jl b/test/runtests.jl index a7c81a7..d07363e 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,4 +1,5 @@ using ProfileView +using Test function profile_test(n) for i = 1:n @@ -52,3 +53,16 @@ ProfileView.view(data, lidict=lidict) ProfileView.closeall() + +# Test `warntype_last` +function add2(x) + y = x[1] + x[2] + return y, backtrace() +end +_, bt = add2(Any[1,2]) +st = stacktrace(bt) +ProfileView.clicked[] = st[1] +io = IOBuffer() +warntype_last(io) +str = String(take!(io)) +@test occursin("Base.getindex(x, 1)::ANY", str)