Page 1 of 1

Is it good practice to keep calling `del` on objects that I don't need anymore?

Posted: Tue Jul 13, 2021 10:22 am
by snake77
Is it good practice to keep calling

Code: Select all

del
on objects as soon as I don't need them anymore? (And not wait until it goes out of scope.)

Or does it not have an immediate effect anyway and would I have to call

Code: Select all

gc.collect()
every time, too? Or does it get called automatically if there would be not enough memory, to see if some memory can be freed up from a `del` call that happened in the meantime?

Re: Is it good practice to keep calling `del` on objects that I don't need anymore?

Posted: Wed Jul 14, 2021 6:20 am
by stijn
del only removes the name from the scope so the object remeains as-is so indeed will not have immediate effect on memory until calling gc.collect(). Which indeed gets called automatically if there is not enough memory for an allocation. Whether it's good practice: depends. Littering your code with del/gc.collect() should imo really be a last resort because it makes things look unreadable and if it is needed it's a sign you're operating at the limit of what your platform can do and/or your code needs improving with respect to memory usage.

Re: Is it good practice to keep calling `del` on objects that I don't need anymore?

Posted: Wed Jul 14, 2021 8:50 am
by pythoncoder
I agree - I never use del. The GC algorithm detects objects which have gone out of scope and reclaims the RAM.

In large applications I run a task which periodically performs gc.collect(). This has three benefits. Firstly, I control when GC occurs so can opt to run it when it has least impact on application behaviour. Secondly, calling it regularly reduces the length of time taken by each invocation. Lastly, calling it regularly reduces RAM fragmentation.

Re: Is it good practice to keep calling `del` on objects that I don't need anymore?

Posted: Wed Jul 14, 2021 12:11 pm
by jimmo
Echoing what pythoncoder and stjin said, you should only call "del" in very specific situations that are quite rare.

In general, if your approach is to break your code up into smaller functions and avoid re-assigning variables then you won't see the sort of problems where you might otherwise reach for "del".

(The point of the smaller functions is that everything goes out of scope at the end of the function and will therefore be immediately available for collection)

Re: Is it good practice to keep calling `del` on objects that I don't need anymore?

Posted: Wed Jul 14, 2021 9:16 pm
by kevinkk525
I only use "del" in long running loops which occasionally create large temporary data structures. (Afterwards I call gc.collect() to free that RAM). That way those variables don't take up unneccessary RAM.

Simple, yet weird example:

Code: Select all

while True: 
    a={}
    a.update(await get_results())
    await asyncio.sleep(10)
    a.update(await get_other_results())
    await publish(a)
    del a
    gc.collect()
    await do_something()
    await asyncio.sleep(10)
    await do_something()
    
Of course this could be avoided by using a function for all "a" related stuff.. I also use it when working with long temporary strings where creating new functions just doesn't work or makes no sense.

So all in all a very special use-case.
Generally "del" is hardly needed.


As for calling gc.collect(), this might look a bit strange but I came to realize that I prefer to call that function whenever I deal with larger data structures or importing modules.
On most devices or smaller projects it won't matter but with my big project on the esp8266 it has an enormous impact. Not calling gc.collect() or calling it at the wrong time makes the difference between having 3kB of continuous free space or not even being able to import all the modules because the RAM is already too fragmented (and that's with frozen modules).
Calling gc.collect() regularly until all modules are imported is an important part in keeping the RAM usable.
Later I call it only after larger data like after I'm done with a big string or dictionary, so that the next function doesn't have to deal with a heavily fragmented heap. (additionally to a regular gc.collect())

Re: Is it good practice to keep calling `del` on objects that I don't need anymore?

Posted: Wed Jul 14, 2021 10:17 pm
by davef
Hi Kevin,
Calling gc.collect() regularly until all modules are imported is an important part in keeping the RAM usable.
I don't understand the "until all modules are imported" part.

I have gc.collect() sprinkled through the code without following what might be good practice. For example ... say I am running a while loop collecting data and once a day I call uMail to send the log. When would be the best times to call gc.collect()? Before calling a .py file that imports umail, before calling a function in umail or after sending the log has finished and I drop back to collecting data?

Thanks

Re: Is it good practice to keep calling `del` on objects that I don't need anymore?

Posted: Thu Jul 15, 2021 5:09 am
by kevinkk525
In my project I import multiple modules. After each import statement I call gc.collect() to free all the RAM that only was only temporarily used during import.
Then I call gc.collect() after creating bigger objects.
This ensures that the RAM is as continuously used as possible and the fragmentation as low as possible.

Code: Select all

import module1
gc.collect()
import module2
gc.collect()
import module3
gc.collect()

obj=module1.Class()
gc.collect()
say I am running a while loop collecting data and once a day I call uMail to send the log. When would be the best times to call gc.collect()? Before calling a .py file that imports umail, before calling a function in umail or after sending the log has finished and I drop back to collecting data?
I'd say after sending the mail you should call gc.collect() to free all temporary stuff. Also as mentioned above after each import. Before calling a function or importing modules is not needed, if collect was called after importing etc.

Re: Is it good practice to keep calling `del` on objects that I don't need anymore?

Posted: Thu Jul 15, 2021 6:56 am
by davef
Thank you for making the use of gc.collect() much clearer.

Re: Is it good practice to keep calling `del` on objects that I don't need anymore?

Posted: Thu Jul 15, 2021 10:10 am
by pythoncoder
kevinkk525 wrote:
Thu Jul 15, 2021 5:09 am
...In my project I import multiple modules. After each import statement I call gc.collect()...
To expand on this, the point is that the statement

Code: Select all

import module
invokes the compiler which converts the Python source to bytecode in RAM. The compiler uses RAM and a subsequent run of GC reclaims this. If the next module requires a block of contiguous RAM, perhaps for a buffer, reclaiming RAM before doing the import reduces the risk of failure.