clingo icon indicating copy to clipboard operation
clingo copied to clipboard

Symbols are stored globally and never freed.

Open rkaminsk opened this issue 4 years ago • 10 comments

Clingo internalizes symbols in global hash tables to only allocate memory for the same symbol once. Currently, symbols are never removed form this hash table. When an application runs for a long time and generates a lot of different symbols, this can lead to memory problems.

Unused symbols should be freed. This could be done via some form of garbage collection or reference counting.

rkaminsk avatar Mar 20 '20 10:03 rkaminsk

Workaround for if you have the problem using multiprocessing.pool.Pool in Python: https://stackoverflow.com/questions/38294608/python-multiprocessing-pool-new-process-for-each-variable. Documentation: https://docs.python.org/3/library/multiprocessing.html#multiprocessing.pool.Pool

chenkins avatar Mar 20 '20 11:03 chenkins

Workaround for if you have the problem using multiprocessing.pool.Pool in Python: https://stackoverflow.com/questions/38294608/python-multiprocessing-pool-new-process-for-each-variable. Documentation: https://docs.python.org/3/library/multiprocessing.html#multiprocessing.pool.Pool

Just be careful when exchanging data between the workers. The classes in the clingo API do not support pickling (and it would defy the attempt to safe memory). If you restrict yourself to python classes for communication, then these can be passed around easily and they will be freed when no longer referenced.

rkaminsk avatar Mar 20 '20 14:03 rkaminsk

@rkaminsk Are symbols freed when a clingo Control object is garbage-collected? E.g.:

import clingo


# Abstraction of long-running business logic
while True:
    clingo_control = clingo.Control()
    clingo_control.load(...)
    for _ in range(3):
        clingo_control.ground((
            ...
        ))
        for model in clingo_control.solve(yield_=True, async_=True):
            for symbol in model.symbols(shown=True):
                ...

0x326 avatar Aug 06 '20 19:08 0x326

@rkaminsk Are symbols freed when a clingo Control object is garbage-collected? E.g.:

No, they are never freed and actually shared between multiple control objects.

rkaminsk avatar Aug 06 '20 20:08 rkaminsk

While a garbage-collection/reference-counting approach of individual symbols is probably the ideal solution, is it possible count references to clingo.Control objects in the meantime and clear the hash table when all clingo.Control objects are garbage-collected by Python?

0x326 avatar Aug 06 '20 21:08 0x326

While a garbage-collection/reference-counting approach of individual symbols is probably the ideal solution, is it possible count references to clingo.Control objects in the meantime and clear the hash table when all clingo.Control objects are garbage-collected by Python?

It is not that easy. The python program might store some other symbol objects. I can have a look if I can provide a function to clear all symbols. But it would be dangerous to use...

rkaminsk avatar Aug 06 '20 21:08 rkaminsk

Hmm. It's probably better to be memory-safe than to provide a function that could result in a segfault. I think some form of memory management is going to be an essential feature for real-world applications, but I can look into using subprocesses in the meantime.

0x326 avatar Aug 06 '20 22:08 0x326

Is there a way with the C/C++ API to do that? It would be really helpful to at least have a manual option, even if the Python binding doesn't support it.

kherud avatar Apr 12 '24 07:04 kherud

The next major clingo release will give more control about storing symbols. For now there is no way to delete them - not even on the C++ level.

rkaminsk avatar Apr 12 '24 07:04 rkaminsk

@rkaminsk That is really nice to read. You once mentioned that this feature has to be well planned. Can you elaborate on how you plan to do it?

sthiele avatar Apr 12 '24 11:04 sthiele