回答此问题可获得 20 贡献值,回答如果被采纳可获得 50 分。
<h2>怎么回事</h2>
<p>在python2.7.8中,我每几分钟通过包<code>netsnmp</code>从几千个网络设备收集数据。我还使用了<code>fastsnmpy</code>,这样我就可以访问(更高效的)netsnmp命令<code>snmpbulkwalk</code>。在</p>
<p>我正在尝试减少脚本使用的内存量。我运行同一脚本的三个实例,在重新查询所有设备以获取所需数据之前,该脚本将休眠两分钟。当我在<code>bash</code>中创建原始脚本时,当同时激活时,它们将使用少于500MB的空间。但是,当我将其转换为Python时,每个实例占用4GB<em>每个</em>,这表明(对我来说)我的数据结构需要更有效地管理。即使在空闲时,它们也要消耗4GB的内存。在</p>
<hr/>
<h2>代码活动</h2>
<p>我的脚本首先创建一个列表,在其中打开一个文件并将目标设备的主机名附加为单独的值。这些通常包含80到1200个名字。在</p>
<pre><code>expand = []
f = open(self.deviceList, 'r')
for line in f:
line = line.strip()
expand.append(line)
</code></pre>
<p>从那里我设置了SNMP会话并执行请求</p>
^{pr2}$
<p>由于这两个SNMP包的行为方式,设备响应被解析成列表并存储到一个巨大的数据结构中。例如</p>
<pre><code>for output in expandresults:
print ouput.hostname, output.iid, output.val
#
host1 1 1
host1 2 2
host1 3 3
host2 1 4
host2 2 5
host2 3 6
# Object 'output' itself cannot be printed directly; the value returned from this is obscure
...
</code></pre>
<p>我必须遍历每个响应,合并相关数据,然后输出每个设备的完整响应。这有点难举个例子</p>
<pre><code>host1,1,2,3
host2,4,5,6
host3,7,8,9,10,11,12
host4,13,14
host5,15,16,17,18
...
</code></pre>
<p>每个设备有不同数量的响应。我不能期望每个设备都有一个统一的任意数量的值组合成一个字符串来写入CSV。在</p>
<hr/>
<h2>我如何处理数据</h2>
<p>我相信在这里我消耗了大量的内存,但我无法解决如何在删除访问数据的同时简化过程。在</p>
<pre><code>expandarrays = dict()
for output in expandresults:
if output.val is not None:
if output.hostname in expandarrays:
expandarrays[output.hostname] += ',' + output.val
else:
expandarrays[output.hostname] = ',' + output.val
for key in expandarrays:
self.WriteOut(key,expandarrays[key])
</code></pre>
<p>目前我正在创建一个新字典,检查设备响应是否为空,然后将响应值附加到一个字符串中,该字符串将用于写入CSV文件。在</p>
<p>问题是,我实际上是在克隆现有的字典,这意味着我使用的系统内存是原来的两倍。当我把它们移到<code>expandarrays</code>时,我想删除我在<code>expandresults</code>中访问过的值,这样我就不用那么多内存了。有没有一种有效的方法?有没有更好的方法来降低代码的复杂性,以便更容易理解?在</p>
<hr/>
<h2>罪魁祸首</h2>
<p>感谢那些回答的人。对于那些将来由于遇到类似问题而偶然发现这个线程的人来说:<code>fastsnmpy</code>包是导致大量使用系统内存的罪魁祸首。<code>multiwalk()</code>函数为每个主机创建一个线程,但是一次创建一个线程,而不是设置某种上限。因为我的脚本的每个实例最多可以处理1200个设备,这意味着在几秒钟内就有1200个线程被实例化和排队。使用<code>bulkwalk()</code>函数比较慢,但仍然足够快,可以满足我的需要。两者之间的差异是4GB和250MB(系统内存使用量)。在</p>