• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

JuliaLang / julia / #37591

pending completion
#37591

push

local

web-flow
Allocation Profiler: Types for all allocations (#50337)

Pass the types to the allocator functions.

-------

Before this PR, we were missing the types for allocations in two cases:

1. allocations from codegen
2. allocations in `gc_managed_realloc_`

The second one is easy: those are always used for buffers, right?

For the first one: we extend the allocation functions called from
codegen, to take the type as a parameter, and set the tag there.

I kept the old interfaces around, since I think that they cannot be
removed due to supporting legacy code?

------

An example of the generated code:
```julia
  %ptls_field6 = getelementptr inbounds {}**, {}*** %4, i64 2
  %13 = bitcast {}*** %ptls_field6 to i8**
  %ptls_load78 = load i8*, i8** %13, align 8
  %box = call noalias nonnull dereferenceable(32) {}* @ijl_gc_pool_alloc_typed(i8* %ptls_load78, i32 1184, i32 32, i64 4366152144) #7
```

Fixes #43688.
Fixes #45268.

Co-authored-by: Valentin Churavy <vchuravy@users.noreply.github.com>

72755 of 84117 relevant lines covered (86.49%)

22738368.36 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

79.38
/stdlib/InteractiveUtils/src/InteractiveUtils.jl
1
# This file is a part of Julia. License is MIT: https://julialang.org/license
2

3
module InteractiveUtils
4

5
Base.Experimental.@optlevel 1
6

7
export apropos, edit, less, code_warntype, code_llvm, code_native, methodswith, varinfo,
8
    versioninfo, subtypes, supertypes, @which, @edit, @less, @functionloc, @code_warntype,
9
    @code_typed, @code_lowered, @code_llvm, @code_native, @time_imports, clipboard
10

11
import Base.Docs.apropos
12

13
using Base: unwrap_unionall, rewrap_unionall, isdeprecated, Bottom, show_unquoted, summarysize,
14
    signature_type, format_bytes
15
using Base.Libc
16
using Markdown
17

18
include("editless.jl")
19
include("codeview.jl")
20
include("macros.jl")
21
include("clipboard.jl")
22

23
"""
24
    varinfo(m::Module=Main, pattern::Regex=r""; all=false, imported=false, recursive=false, sortby::Symbol=:name, minsize::Int=0)
25

26
Return a markdown table giving information about exported global variables in a module, optionally restricted
27
to those matching `pattern`.
28

29
The memory consumption estimate is an approximate lower bound on the size of the internal structure of the object.
30

31
- `all` : also list non-exported objects defined in the module, deprecated objects, and compiler-generated objects.
32
- `imported` : also list objects explicitly imported from other modules.
33
- `recursive` : recursively include objects in sub-modules, observing the same settings in each.
34
- `sortby` : the column to sort results by. Options are `:name` (default), `:size`, and `:summary`.
35
- `minsize` : only includes objects with size at least `minsize` bytes. Defaults to `0`.
36

37
The output of `varinfo` is intended for display purposes only.  See also [`names`](@ref) to get an array of symbols defined in
38
a module, which is suitable for more general manipulations.
39
"""
40
function varinfo(m::Module=Base.active_module(), pattern::Regex=r""; all::Bool = false, imported::Bool = false, recursive::Bool = false, sortby::Symbol = :name, minsize::Int=0)
32✔
41
    sortby in (:name, :size, :summary) || throw(ArgumentError("Unrecognized `sortby` value `:$sortby`. Possible options are `:name`, `:size`, and `:summary`"))
11✔
42
    rows = Vector{Any}[]
11✔
43
    workqueue = [(m, ""),]
11✔
44
    while !isempty(workqueue)
23✔
45
        m2, prep = popfirst!(workqueue)
12✔
46
        for v in names(m2; all, imported)
12✔
47
            if !isdefined(m2, v) || !occursin(pattern, string(v))
150✔
48
                continue
16✔
49
            end
50
            value = getfield(m2, v)
59✔
51
            isbuiltin = value === Base || value === Base.active_module() || value === Core
118✔
52
            if recursive && !isbuiltin && isa(value, Module) && value !== m2 && nameof(value) === v && parentmodule(value) === m2
59✔
53
                push!(workqueue, (value, "$prep$v."))
1✔
54
            end
55
            ssize_str, ssize = if isbuiltin
59✔
56
                    ("", typemax(Int))
×
57
                else
58
                    ss = summarysize(value)
59✔
59
                    (format_bytes(ss), ss)
118✔
60
                end
61
            if ssize >= minsize
59✔
62
                push!(rows, Any[string(prep, v), ssize_str, summary(value), ssize])
55✔
63
            end
64
        end
87✔
65
    end
12✔
66
    let (col, rev) = if sortby === :name
11✔
67
            1, false
9✔
68
        elseif sortby === :size
2✔
69
            4, true
1✔
70
        elseif sortby === :summary
1✔
71
            3, false
1✔
72
        else
73
            @assert "unreachable"
14✔
74
        end
75
        sort!(rows; by=r->r[col], rev)
190✔
76
    end
77
    pushfirst!(rows, Any["name", "size", "summary"])
33✔
78

79
    return Markdown.MD(Any[Markdown.Table(map(r->r[1:3], rows), Symbol[:l, :r, :l])])
77✔
80
end
81
varinfo(pat::Regex; kwargs...) = varinfo(Base.active_module(), pat; kwargs...)
×
82

83
"""
84
    versioninfo(io::IO=stdout; verbose::Bool=false)
85

86
Print information about the version of Julia in use. The output is
87
controlled with boolean keyword arguments:
88

89
- `verbose`: print all additional information
90

91
!!! warning "Warning"
92
    The output of this function may contain sensitive information. Before sharing the output,
93
    please review the output and remove any data that should not be shared publicly.
94

95
See also: [`VERSION`](@ref).
96
"""
97
function versioninfo(io::IO=stdout; verbose::Bool=false)
15✔
98
    println(io, "Julia Version $VERSION")
6✔
99
    if !isempty(Base.GIT_VERSION_INFO.commit_short)
6✔
100
        println(io, "Commit $(Base.GIT_VERSION_INFO.commit_short) ($(Base.GIT_VERSION_INFO.date_string))")
6✔
101
    end
102
    official_release = Base.TAGGED_RELEASE_BANNER == "Official https://julialang.org/ release"
6✔
103
    if Base.isdebugbuild() || !isempty(Base.TAGGED_RELEASE_BANNER) || (Base.GIT_VERSION_INFO.tagged_commit && !official_release)
12✔
104
        println(io, "Build Info:")
×
105
        if Base.isdebugbuild()
×
106
            println(io, "  DEBUG build")
×
107
        end
108
        if !isempty(Base.TAGGED_RELEASE_BANNER)
×
109
            println(io, "  ", Base.TAGGED_RELEASE_BANNER)
×
110
        end
111
        if Base.GIT_VERSION_INFO.tagged_commit && !official_release
×
112
            println(io,
×
113
                """
114

115
                    Note: This is an unofficial build, please report bugs to the project
116
                    responsible for this build and not to the Julia project unless you can
117
                    reproduce the issue using official builds available at https://julialang.org/downloads
118
                """
119
            )
120
        end
121
    end
122
    println(io, "Platform Info:")
6✔
123
    println(io, "  OS: ", Sys.iswindows() ? "Windows" : Sys.isapple() ?
6✔
124
        "macOS" : Sys.KERNEL, " (", Sys.MACHINE, ")")
125

126
    if verbose
6✔
127
        lsb = ""
1✔
128
        if Sys.islinux()
1✔
129
            try lsb = readchomp(pipeline(`lsb_release -ds`, stderr=devnull)); catch; end
3✔
130
        end
131
        if Sys.iswindows()
1✔
132
            try lsb = strip(read(`$(ENV["COMSPEC"]) /c ver`, String)); catch; end
×
133
        end
134
        if !isempty(lsb)
2✔
135
            println(io, "      ", lsb)
×
136
        end
137
        if Sys.isunix()
1✔
138
            println(io, "  uname: ", readchomp(`uname -mprsv`))
1✔
139
        end
140
    end
141

142
    if verbose
6✔
143
        cpuio = IOBuffer() # print cpu_summary with correct alignment
1✔
144
        Sys.cpu_summary(cpuio)
1✔
145
        for (i, line) in enumerate(split(chomp(String(take!(cpuio))), "\n"))
2✔
146
            prefix = i == 1 ? "  CPU: " : "       "
3✔
147
            println(io, prefix, line)
3✔
148
        end
5✔
149
    else
150
        cpu = Sys.cpu_info()
5✔
151
        println(io, "  CPU: ", length(cpu), " × ", cpu[1].model)
5✔
152
    end
153

154
    if verbose
6✔
155
        println(io, "  Memory: $(Sys.total_memory()/2^30) GB ($(Sys.free_memory()/2^20) MB free)")
2✔
156
        try println(io, "  Uptime: $(Sys.uptime()) sec"); catch; end
2✔
157
        print(io, "  Load Avg: ")
1✔
158
        Base.print_matrix(io, Sys.loadavg()')
1✔
159
        println(io)
1✔
160
    end
161
    println(io, "  WORD_SIZE: ", Sys.WORD_SIZE)
6✔
162
    println(io, "  LIBM: ",Base.libm_name)
6✔
163
    println(io, "  LLVM: libLLVM-",Base.libllvm_version," (", Sys.JIT, ", ", Sys.CPU_NAME, ")")
6✔
164
    println(io, "  Threads: ", Threads.maxthreadid(), " on ", Sys.CPU_THREADS, " virtual cores")
6✔
165

166
    function is_nonverbose_env(k::String)
541✔
167
        return occursin(r"^JULIA_|^DYLD_|^LD_", k)
535✔
168
    end
169
    function is_verbose_env(k::String)
135✔
170
        return occursin(r"PATH|FLAG|^TERM$|HOME", k) && !is_nonverbose_env(k)
129✔
171
    end
172
    env_strs = String[
11✔
173
        String["  $(k) = $(v)" for (k,v) in ENV if is_nonverbose_env(uppercase(k))];
174
        (verbose ?
175
         String["  $(k) = $(v)" for (k,v) in ENV if is_verbose_env(uppercase(k))] :
176
         String[]);
177
    ]
178
    if !isempty(env_strs)
6✔
179
        println(io, "Environment:")
5✔
180
        for str in env_strs
5✔
181
            println(io, str)
35✔
182
        end
36✔
183
    end
184
end
185

186

187
function type_close_enough(@nospecialize(x), @nospecialize(t))
85,469✔
188
    x == t && return true
85,469✔
189
    # TODO: handle UnionAll properly
190
    return (isa(x, DataType) && isa(t, DataType) && x.name === t.name && x <: t) ||
85,035✔
191
           (isa(x, Union) && isa(t, DataType) && (type_close_enough(x.a, t) || type_close_enough(x.b, t)))
192
end
193

194
# `methodswith` -- shows a list of methods using the type given
195
"""
196
    methodswith(typ[, module or function]; supertypes::Bool=false])
197

198
Return an array of methods with an argument of type `typ`.
199

200
The optional second argument restricts the search to a particular module or function
201
(the default is all top-level modules).
202

203
If keyword `supertypes` is `true`, also return arguments with a parent type of `typ`,
204
excluding type `Any`.
205
"""
206
function methodswith(@nospecialize(t::Type), @nospecialize(f::Base.Callable), meths = Method[]; supertypes::Bool=false)
6,654✔
207
    for d in methods(f)
6,554✔
208
        if any(function (x)
100,930✔
209
                   let x = rewrap_unionall(x, d.sig)
88,747✔
210
                       (type_close_enough(x, t) ||
73,828✔
211
                        (supertypes ? (isa(x, Type) && t <: x && (!isa(x,TypeVar) || x.ub != Any)) :
212
                         (isa(x,TypeVar) && x.ub != Any && t == x.ub)) &&
213
                        x != Any)
214
                   end
215
               end,
216
               unwrap_unionall(d.sig).parameters)
217
            push!(meths, d)
434✔
218
        end
219
    end
50,977✔
220
    return meths
3,327✔
221
end
222

223
function _methodswith(@nospecialize(t::Type), m::Module, supertypes::Bool)
88✔
224
    meths = Method[]
88✔
225
    for nm in names(m)
88✔
226
        if isdefined(m, nm)
5,521✔
227
            f = getfield(m, nm)
5,521✔
228
            if isa(f, Base.Callable)
5,521✔
229
                methodswith(t, f, meths; supertypes = supertypes)
4,150✔
230
            end
231
        end
232
    end
5,609✔
233
    return unique(meths)
88✔
234
end
235

236
methodswith(@nospecialize(t::Type), m::Module; supertypes::Bool=false) = _methodswith(t, m, supertypes)
4✔
237

238
function methodswith(@nospecialize(t::Type); supertypes::Bool=false)
4✔
239
    meths = Method[]
2✔
240
    for mod in Base.loaded_modules_array()
2✔
241
        append!(meths, _methodswith(t, mod, supertypes))
86✔
242
    end
88✔
243
    return unique(meths)
2✔
244
end
245

246
# subtypes
247
function _subtypes_in!(mods::Array, x::Type)
9✔
248
    xt = unwrap_unionall(x)
9✔
249
    if !isabstracttype(x) || !isa(xt, DataType)
16✔
250
        # Fast path
251
        return Type[]
2✔
252
    end
253
    sts = Vector{Any}()
7✔
254
    while !isempty(mods)
1,009✔
255
        m = pop!(mods)
1,002✔
256
        xt = xt::DataType
1,002✔
257
        for s in names(m, all = true)
1,002✔
258
            if isdefined(m, s) && !isdeprecated(m, s)
204,083✔
259
                t = getfield(m, s)
204,069✔
260
                dt = isa(t, UnionAll) ? unwrap_unionall(t) : t
204,069✔
261
                if isa(dt, DataType)
204,069✔
262
                    if dt.name.name === s && dt.name.module == m && supertype(dt).name == xt.name
98,117✔
263
                        ti = typeintersect(t, x)
20✔
264
                        ti != Bottom && push!(sts, ti)
20✔
265
                    end
266
                elseif isa(t, Module) && nameof(t) === s && parentmodule(t) === m && t !== m
105,952✔
267
                    t === Base || push!(mods, t) # exclude Base, since it also parented by Main
714✔
268
                end
269
            end
270
        end
205,085✔
271
    end
1,002✔
272
    return permute!(sts, sortperm(map(string, sts)))
7✔
273
end
274

275
subtypes(m::Module, x::Type) = _subtypes_in!([m], x)
×
276

277
"""
278
    subtypes(T::DataType)
279

280
Return a list of immediate subtypes of DataType `T`. Note that all currently loaded subtypes
281
are included, including those not visible in the current module.
282

283
See also [`supertype`](@ref), [`supertypes`](@ref), [`methodswith`](@ref).
284

285
# Examples
286
```jldoctest
287
julia> subtypes(Integer)
288
3-element Vector{Any}:
289
 Bool
290
 Signed
291
 Unsigned
292
```
293
"""
294
subtypes(x::Type) = _subtypes_in!(Base.loaded_modules_array(), x)
9✔
295

296
"""
297
    supertypes(T::Type)
298

299
Return a tuple `(T, ..., Any)` of `T` and all its supertypes, as determined by
300
successive calls to the [`supertype`](@ref) function, listed in order of `<:`
301
and terminated by `Any`.
302

303
See also [`subtypes`](@ref).
304

305
# Examples
306
```jldoctest
307
julia> supertypes(Int)
308
(Int64, Signed, Integer, Real, Number, Any)
309
```
310
"""
311
function supertypes(T::Type)
10✔
312
    S = supertype(T)
16✔
313
    # note: we return a tuple here, not an Array as for subtypes, because in
314
    #       the future we could evaluate this function statically if desired.
315
    return S === T ? (T,) : (T, supertypes(S)...)
10✔
316
end
317

318
# TODO: @deprecate peakflops to LinearAlgebra
319
export peakflops
320
"""
321
    peakflops(n::Integer=4096; eltype::DataType=Float64, ntrials::Integer=3, parallel::Bool=false)
322

323
`peakflops` computes the peak flop rate of the computer by using double precision
324
[`gemm!`](@ref LinearAlgebra.BLAS.gemm!). For more information see
325
[`LinearAlgebra.peakflops`](@ref).
326

327
!!! compat "Julia 1.1"
328
    This function will be moved from `InteractiveUtils` to `LinearAlgebra` in the
329
    future. In Julia 1.1 and later it is available as `LinearAlgebra.peakflops`.
330
"""
331
function peakflops(n::Integer=4096; eltype::DataType=Float64, ntrials::Integer=3, parallel::Bool=false)
×
332
    # Base.depwarn("`peakflops` has moved to the LinearAlgebra module, " *
333
    #              "add `using LinearAlgebra` to your imports.", :peakflops)
334
    let LinearAlgebra = Base.require(Base.PkgId(
×
335
            Base.UUID((0x37e2e46d_f89d_539d,0xb4ee_838fcccc9c8e)), "LinearAlgebra"))
336
        return LinearAlgebra.peakflops(n, eltype=eltype, ntrials=ntrials, parallel=parallel)
×
337
    end
338
end
339

340
function report_bug(kind)
×
341
    @info "Loading BugReporting package..."
×
342
    BugReportingId = Base.PkgId(
×
343
        Base.UUID((0xbcf9a6e7_4020_453c,0xb88e_690564246bb8)), "BugReporting")
344
    # Check if the BugReporting package exists in the current environment
345
    local BugReporting
×
346
    if Base.locate_package(BugReportingId) === nothing
×
347
        @info "Package `BugReporting` not found - attempting temporary installation"
×
348
        # Create a temporary environment and add BugReporting
349
        let Pkg = Base.require(Base.PkgId(
×
350
            Base.UUID((0x44cfe95a_1eb2_52ea,0xb672_e2afdf69b78f)), "Pkg"))
351
            mktempdir() do tmp
×
352
                old_load_path = copy(LOAD_PATH)
×
353
                push!(empty!(LOAD_PATH), joinpath(tmp, "Project.toml"))
×
354
                old_active_project = Base.ACTIVE_PROJECT[]
×
355
                Base.ACTIVE_PROJECT[] = nothing
×
356
                Pkg.add(Pkg.PackageSpec(BugReportingId.name, BugReportingId.uuid))
×
357
                BugReporting = Base.require(BugReportingId)
×
358
                append!(empty!(LOAD_PATH), old_load_path)
×
359
                Base.ACTIVE_PROJECT[] = old_active_project
×
360
            end
361
        end
362
    else
363
        BugReporting = Base.require(BugReportingId)
×
364
    end
365
    return Base.invokelatest(BugReporting.make_interactive_report, kind, ARGS)
×
366
end
367

368
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc