Listing names and sizes of local variables

I am doing some debugging to try and find a memory leak. I would like to be able to see the size of every local variable inside of a function. InteractiveUtils.jl seemed like a promising solution, but, being “interactive,” it will only show the information I want if it’s in the global scope.

Consider the following MWE:

using Random, InteractiveUtils

Random.seed!(123456)

function inside(z)
    y = z./100
    return y
end

function wrapper()
    x = 1_000 .* rand(1_000)
    w = inside(x)
    @show varinfo()
    return w
end

@show varinfo()
p = wrapper()
@show varinfo()

What I would like is to see the sizes of w and x inside of the wrapper function. But instead I only get the following because of the local scope.

| name             |        size | summary         |
|:---------------- | -----------:|:--------------- |
| Base             |             | Module          |
| Core             |             | Module          |
| InteractiveUtils | 183.034 KiB | Module          |
| Main             |             | Module          |
| inside           |     0 bytes | typeof(inside)  |
| wrapper          |     0 bytes | typeof(wrapper) |

If anyone has ideas about how to see sizes of local variables, I would be most grateful. I have consulted this and this Discourse topics already. They have been helpful, but not quite what I am looking for.

I am completely naive here, but shouldn’t the size of an array just be a function of its size and element type, and it is independent of scope? Or are your actual types more complicated than arrays?

You’re correct: I’m just using arrays and DataFrames. Is there a source I could consult that would map “number of elements in a Float64 array” to “number of MB occupying RAM”? I’m no computer scientist. But I would happily write my own function that could do this calculation for me.

I was thinking you could just println(size(w)) or something from inside whatever function you want to peek into, then you can create that variable in the REPL and call varinfo() to see how big it is.

Someone might well come along and correct me on this, but I think that a float is 8 bytes. So 100 floats is something like 800 bytes + some overhead,

x                  840 bytes 100-element Vector{Float64}
2 Likes

Here’s an even better solution: Base.summarysize()! Modifying the MWE from above:

using Random, InteractiveUtils

Random.seed!(123456)

function inside(z)
    y = z./100
    return y
end

function wrapper()
    x = 1_000 .* rand(1_000)
    w = inside(x)
    @show Base.summarysize(x)/1024
    @show Base.summarysize(w)/1024
    return w
end

p = wrapper()
@show varinfo()

which returns

Base.summarysize(x) / 1024 = 7.8515625
Base.summarysize(w) / 1024 = 7.8515625
varinfo() = | name             |        size | summary                       |
|:---------------- | -----------:|:----------------------------- |
| Base             |             | Module                        |
| Core             |             | Module                        |
| InteractiveUtils | 182.987 KiB | Module                        |
| Main             |             | Module                        |
| inside           |     0 bytes | typeof(inside)                |
| p                |   7.852 KiB | 1000-element Array{Float64,1} |
| wrapper          |     0 bytes | typeof(wrapper)               |
2 Likes