是内存泄露还是我不懂垃圾回收和内存管理?

Is there a memory leak or do I not understand garbage collection and memory management?

这是我正在使用的第三方库中的内存泄漏,还是我不了解Python垃圾收集和内存管理方面的内容?

最后,我假设内存使用量接近开始时的内存使用量 (33MB),因为我没有对在 do_griddly_work() 中创建的对象的任何引用。但是,内存使用率更高(1600MB),并且在退出函数或收集垃圾后不会下降。

这是打印出来的

Before any work:  33.6953125 MB
After griddly work:  1601.60546875 MB
0
After garbage collect:  1601.60546875 MB

通过以下代码

from griddly import GymWrapperFactory, gd, GymWrapper
import gc
import os, psutil

def do_griddly_work():
    current_path = os.path.dirname(os.path.realpath(__file__))
    env = GymWrapper(current_path + '/griddly_descriptions/testbed1.yaml',
                     player_observer_type=gd.ObserverType.VECTOR,
                     global_observer_type=gd.ObserverType.SPRITE_2D,
                     level=0)
    env.reset()
    for _ in range(10000):
        c_env = env.clone()
    # Print memory usage after work
    print('After griddly work: ', psutil.Process(os.getpid()).memory_info().rss / 1024 ** 2, 'MB')


if __name__ == '__main__':
    process = psutil.Process(os.getpid())

    # Memory usage before work = ~33MB
    print('Before any work: ', process.memory_info().rss / 1024 ** 2, 'MB')
    
    # Do work that clones an environment a lot
    do_griddly_work()
    
    # Collect garbage
    print(gc.collect())
    
    # Memory usage after work = ~1600 MB
    print('After garbage collect: ', process.memory_info().rss / 1024 ** 2, 'MB')

大多数语言,包括 Python,都没有义务在对象被销毁后将内存释放回 OS。事实上,因为 OS 分配通常是在比单个对象大得多的块中进行的,该块将包含多个对象,如果其中任何一个仍然存在,它将 不可能 到 return 它到 OS.

memory_info().rss 从 OS 的角度报告已用内存,而不是 Python 运行时的角度。

问题已被我使用的 Griddly 库的作者解决。 Python 垃圾回收无法访问克隆的环境,底层 C++ 实现中存在内存泄漏。