找不到Python程序大量DATA列内存消耗的来源



我正在开发一个python应用程序,其中有很多我自己的包和类,其中RAM约束非常重要。我正在使用超时实用程序从外部监视此约束。令我惊讶的是,如果虚拟机限制低于800MB,我的程序在一开始就无声地失败了。

为了进行调查,我使用了psutil的memory_info来更深入地了解正在发生的事情。我把这个方法放在if __name__ == '__main__':块的最开头(所以,在执行程序的任何逻辑之前)。结果如下:pmem(rss=94330880, vms=792522752, shared=35758080, text=2834432, lib=0, data=650641408, dirty=0)

所以data字段在程序一开始就已经占用了650MB !我想也许问题出在main.py顶部的输入,这里是tracemalloc的输入:

<frozen importlib._bootstrap_external>:672: size=105 KiB, count=973, average=111 B
/usr/lib/python3.10/abc.py:106: size=4326 B, count=11, average=393 B
/usr/lib/python3.10/statistics.py:1051: size=2585 B, count=10, average=258 B
/usr/lib/python3.10/abc.py:107: size=2520 B, count=42, average=60 B
/usr/lib/python3.10/statistics.py:436: size=2352 B, count=2, average=1176 B
<frozen importlib._bootstrap_external>:128: size=2339 B, count=17, average=138 B
/home/tatiana/Documents/project/utils/utils.py:6: size=1944 B, count=12, average=162 B
/usr/lib/python3.10/statistics.py:144: size=1928 B, count=10, average=193 B
/home/tatiana/Documents/project/package/Seed.py:5: size=1872 B, count=8, average=234 B
/usr/lib/python3.10/collections/__init__.py:481: size=1835 B, count=8, average=229 B

所以进口似乎不是问题。在VM上,从Github下载项目后,我得到了DATA字段的250MB消耗,虽然少了,但看起来仍然大得不合理。在我的机器和虚拟机上,我都使用Ubuntu 22.04。

编辑:所以我现在有两个目标:
  1. 找出为什么程序的内存消耗如此之大,不同的测量方式不同(这是我目前正在努力和需要帮助的地方)。
  2. 减少内存使用的方式,程序可以运行与800MB可用的RAM,更好的少(阻塞1,但当1解决,可以做到这一点我自己)

下面是pythonmemory_profilermain()函数的输出:

Line #    Mem usage    Increment  Occurrences   Line Contents
=============================================================
36     93.0 MiB     93.0 MiB           1   @profile
37                                         def main():
38     93.0 MiB      0.0 MiB           1       cli_args = read_cli()
39                                         
40     93.0 MiB      0.0 MiB           1       dataLoader = DataLoader(cli_args['src_1'], cli_args['seed_pool_size'])
41     98.7 MiB      5.7 MiB           1       seeds = dataLoader.loadData()
42                                         
43     98.7 MiB      0.0 MiB           1       list_1 = []
44     98.7 MiB      0.0 MiB           2       list_params = {'source_2': cli_args['src_2'], 'pool_size': cli_args['seed_pool_size'],
45     98.7 MiB      0.0 MiB           1                          'percent_of_len': 1}
46                                         
47    106.7 MiB      0.0 MiB           2       for list_el in cli_args['list_els']:
48     98.7 MiB      0.0 MiB           1           concreteEl = getattr(import_module("generator." + list_el), list_el)
49    106.7 MiB      8.0 MiB           1           list_1.append(concreteEl(list_params))
50                                         
51    106.7 MiB      0.0 MiB           1       Strategy = getattr(import_module("generator.strategies." + cli_args['strategy']), cli_args['strategy'])
52    106.7 MiB      0.0 MiB           1       strategy = Strategy(seeds, list_1, dataLoader)
53                                         
54    106.8 MiB      0.1 MiB           2       Features = getattr(import_module("featurefeeder.featuretypes." + cli_args['features']),
55    106.8 MiB      0.0 MiB           1                          cli_args['features'])
56    106.8 MiB      0.0 MiB           1       feature_extractor = Features()
57                                         
58    141.5 MiB     34.8 MiB           1       Model = getattr(import_module("dut.models." + cli_args['model']), cli_args['model'])
59    142.0 MiB      0.4 MiB           1       model = Model(cli_args['model_src'])
60                                         
61    142.0 MiB      0.0 MiB           1       coverage = Coverage()
62    142.0 MiB      0.0 MiB           1       monitor = Monitor(coverage, strategy)
63                                         
64    144.4 MiB      2.4 MiB           1       run(cli_args['epochs'], strategy, feature_extractor, model, coverage, monitor)

但是,如果我将内存限制设置为800MB,则失败,超时输出如下:MEM CPU 2.78 MEM 807556 MAXMEM 807556 STALE 0 MAXMEM_RSS 121552

所以对我来说有趣的是为什么,即使memory_profilermain()函数的最后一条指令结束时显示144.4 MiB内存使用情况,超时仍然显示MAXMEM 845748?从实用程序代码中,我发现这是Linux中的虚拟内存大小,所以我认为差异来自于内存分析器只测量使用的物理RAM (=rss)这一事实。下一个也是最后一个问题是如何减少虚拟内存的使用?首先,我检查了所有未使用的/通配符导入,一切似乎都很好,我的下一个想法是堆分配。

任何进一步调查这个问题的方向将非常感谢!

我建议您看一下内存分析器pip install memory-profiler

最新更新