Tracking occupied memory

Is there any way to track occupied memory in Julia? Unfortunately I can’t provide a MWE but the code does something like this:

struct State
    params::@NamedTuple begin
       ... # Bunch of vectors and matrices of Float64
    end
    aux::@NamedTuple begin
        ... # Different set of vectors and matrices
    end
end

mutable struct Chain{T<:NamedTuple, S<:State}
    state::S
    past_states::Vector{T}
end

function f!(chain::Chain)
    state = update(chain.state)
    push!(chain.past_states, state.parameters)
    chain.state = state
end

state = ... # some randomly initialized state
chain = Chain(state, [state.parameters])

for _ in 1:10000
    f!(chain)
end

So now when i run varinfo(), I correctly see that chain has about 8GB in memory. But then I run

chain = nothing
GC.gc()

and the memory remains occupied. I tried coming up with a simpler example but the memory cleared. My guess is that something is happening in update that causes some of the internals of chain to remain referenced even after I reassign chain to nothing.

Is there anyway to check what’s holding that memory? Note that update does use threading, but this happens even if the number of threads is one.