Removing objects on memory, again. Alternatives to A = nothing?


#1

I know the documentations says:

Julia does not have an analog of MATLAB’s clear function; once a name is defined in a Julia session (technically, in module Main ), it is always present.

If memory usage is your concern, you can always replace objects with ones that consume less memory. For example, if A is a gigabyte-sized array that you no longer need, you can free the memory with A = nothing . The memory will be released the next time the garbage collector runs; you can force this to happen with gc() . Moreover, an attempt to use A will likely result in an error, because most methods are not defined on type Nothing .

This has been discussed some time ago but I didn’t want to post on old threads because it’s not well regarded here.
Anyway, the only solution provided there was replacing the content with nothing or forcing the user to use let blocks or local variables.

Is this situation going change at any time soon?
Replacing the content of the object with nothing is not the solution. The user can end up having hundreds of nothing objects. Listing all variables or quickly searching for anything on memory can be a chaos.

Most programming languages do have ways to remove objects from memory.

The problem is even worse when you cannot remove a function method.


#2

Why do you have hundreds of global variables with different names?


#3

It is.

What would be the problem with that? It is costless.

That said, if you are really working with hundreds of globals at the same time, and they are all large, perhaps you should reconsider your approach.

Julia differs from eg R in that while introspection of and operations on the global namespace Main is possible, it is not idiomatic for most code (even scripts). Again, if you have a lot going on in your global namespace, you are probably suffering from all sorts of efficiency and style issues.

Are you aware of Base.delete_method? But again, not something you are meant to use on a regular basis.


#4

For example I have different datasets, each one saved on a variable, or different modifications of something.
Or maybe I just have 5 variables but if don’t need them anymore, I won’t sleep easy if I know the variable is still there, watching me.

Anyway, why do you, Julia developers, think having an rm() command can hurt or be bad in any way?


#5

Because we’re mean, nasty people :smiling_imp:

Nah, just kidding. It’s because being able to undefine things that have already been defined is pretty fundamentally incompatible with many assumptions that the Julia compiler makes when generating code. Those assumptions could potentially be relaxed but it would entail a lot of annoying work for a feature that isn’t strictly necessary and doesn’t really help you do anything.

It might be possible these days to implement this feature by creating a new Main module and copying all the bindings from the old Main into the new one except for the ones that you want to clear and then throwing out the old Main. However, there are a some major caveats to that approach:

  1. This won’t free any memory since there will still be references to the old Main module.
  2. It also won’t handle functions that refer to old globals correctly since the functions will still use the old versions of these globals in the old Main module.

So the better way to do this feature may be to just allow non-const globals to be put back into the undef state that globals can be in before they are first defined. That’s a significant compiler project, however, and pretty hard to motivate. Where would you rank it on the list of compiler work priorities? I find it hard to put it anywhere but the very bottom (even if we added quite a few other projects I can think of to the list). Of course, maybe it would be a good first project for someone looking to get into compiler work.


#6

I just have 5 variables (a, b, c, d, e) but if don’t need them anymore, I won’t sleep easy if I know the [variables are] still there, watching me.

a = b = c = d = e = nothing

#7
names(Main) |> x -> filter(name -> name ∉ [:Base, :Core, :InteractiveUtils, :Main], x) |> x -> map(name -> eval(:($name = nothing)), x)

#8

Note that the above fails for functions. Here’s an alternative that also deletes methods:

for name in names(Main)
    eval(:(
        $name isa Function ? Base.delete_method.(methods($name)) :
            $name isa Module || ($name = nothing)))
end

#9

Yeah, this is a much better solution. I was merely trying to point out, quickly, that Julia has meta-programming facilities that should enable a developer to accomplish quite a lot in this realm. I think, in general, if something can be accomplished in a library, it is better done there than in the core language.