3

我写了一个小程序,使用MinimalModbus通过串口收集数据。数据被转储到CSV文件中。我在SO和其他地方阅读过几篇文章。提到有几件事情是:Python程序吃掉内存

  1. 使用懒评价尽可能(x范围,而不是范围)
  2. 删除大量无用的对象
  3. 使用的子进程,并在他们的死亡记忆是由OS发布

脚本在github上here。我还使用script定期将这些文件上传到服务器。 这两个脚本都相当简单。系统上也没有别的东西在运行,因此我觉得在这两个系统中只有内存占用正在发生。 什么是解决这个问题的最好方法。我不是最愿意采用子流程的。

一些详细信息:

  1. 数据收集是在树莓派(512 MB RAM)
  2. Python版本:2.7
  3. 大约需要3-4天的RAM完全被使用之后, RaspberryPi冻结

我跟着this指南找出前20个正在吃RAM的程序。

$ ps aux | awk '{print $2, $4, $11}' | sort -k2rn | head -n 20 
12434 2.2 python 
12338 1.2 python 
2578 0.8 /usr/sbin/console-kit-daemon 
30259 0.7 sshd: 
30283 0.7 -bash 
1772 0.6 /usr/sbin/rsyslogd 
2645 0.6 /usr/lib/policykit-1/polkitd 
2146 0.5 dhclient 
1911 0.4 /usr/sbin/ntpd 
12337 0.3 sudo 
12433 0.3 sudo 
1981 0.3 sudo 
30280 0.3 sshd: 
154 0.2 udevd 
16994 0.2 /usr/sbin/sshd 
17006 0.2 ps 
1875 0.2 /usr/bin/dbus-daemon 
278 0.2 udevd 
290 0.2 udevd 
1 0.1 init 

因此,这两个Python进程吃掉了一些RAM,但与整体RAM消耗相比,这是非常小的。以下是free命令的输出。

[email protected] ~ $ free -m 
      total  used  free  shared buffers  cached 
Mem:   438  414   23   0   45  320 
-/+ buffers/cache:   48  389 
Swap:   99   0   99 

以下是top命令的输出。

Tasks: 69 total, 1 running, 68 sleeping, 0 stopped, 0 zombie 
%Cpu(s): 66.9 us, 5.0 sy, 0.0 ni, 18.1 id, 0.0 wa, 0.0 hi, 10.0 si, 0.0 st 
KiB Mem: 448776 total, 429160 used, 19616 free, 47016 buffers 
KiB Swap: 102396 total,  0 used, 102396 free, 332288 cached 

PID USER  PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND   
12338 root 20 0 10156 5644 2384 S 69.8 1.3 3059:31 python    
26039 root 20 0  0 0 0 S 1.6 0.0 0:02.71 kworker/0:1  
26863 pi  20 0 4664 1356 1028 R 1.3 0.3 0:00.12 top    
1982 root  20 0 1752 516 448 S 0.3 0.1 1:08.36 sh     
1985 root  20 0 1692 552 460 S 0.3 0.1 5:15.16 startpar   
1 root  20 0 2144 728 620 S 0.0 0.2 0:17.43 init    
2 root  20 0  0 0 0 S 0.0 0.0 0:00.14 kthreadd   
3 root  20 0  0 0 0 S 0.0 0.0 0:13.20 ksoftirqd/0  
5 root   0 -20  0 0 0 S 0.0 0.0 0:00.00 kworker/0:0H  
7 root   0 -20  0 0 0 S 0.0 0.0 0:00.00 kworker/u:0H  
8 root   0 -20  0 0 0 S 0.0 0.0 0:00.00 khelper   
9 root  20 0  0 0 0 S 0.0 0.0 0:00.00 kdevtmpfs   
10 root  0 -20  0 0 0 S 0.0 0.0 0:00.00 netns    
12 root  20 0  0 0 0 S 0.0 0.0 0:00.06 bdi-default  
13 root  0 -20  0 0 0 S 0.0 0.0 0:00.00 kblockd 

EDIT 2

正如在第一个答案的建议,我决定看看日志文件。我看了一下syslog,下面是尾巴的结果。

May 19 10:03:26 raspberrypi wpa_supplicant[7065]: wlan0: Failed to initialize driver interface 
May 19 10:03:49 raspberrypi wpa_supplicant[7157]: nl80211: 'nl80211' generic netlink not found 
May 19 10:03:49 raspberrypi wpa_supplicant[7157]: Failed to initialize driver 'nl80211' 
May 19 10:03:49 raspberrypi wpa_supplicant[7157]: rfkill: Cannot open RFKILL control device 
May 19 10:03:49 raspberrypi wpa_supplicant[7157]: Could not read interface wlan0 flags: No such device 

这些消息填满了日志文件,并且每秒都会传出。有趣的部分是我使用以太网而不是WiFi。

因此,现在还不清楚RA​​M在哪里?

+0

使用软件包管理器从系统中删除wpa_supplicant。 –

回答

3

你的大部分RAM对于应用程序是免费的,因为它用于缓冲区和缓存。看看“ -/+ buffers/cache:”这一行,看看的内存使用量是多少 used/free。解释可以发现here

要验证Python是否在泄漏内存,请随时监控python的RSS大小(或%mem)。例如。编写一个shell脚本,该脚本每隔几个小时从cron作业调用,以将ps命令链的输出和free命令的输出附加到文件。

如果您发现Python进程泄漏内存,您可以执行一些操作;

  • 将您的脚本修改为它在24小时后分机并使用例如一个cron作业来重启它(简单的出路)。
  • 深入了解Python本身,特别是你正在使用的扩展模块。使用gc模块来监视和影响内存使用情况。你可以例如定期拨打gc.count()以监测标记为收集的物体数量。您可以明确地调用gc.collect()并查看是否会减少内存使用量。您还可以修改收集阈值。

如果Python的RAM使用不会随着时间增加,它可能是守护进程的另一个程序。我上面提到的内存日志脚本应该告诉你它是哪一个。

还有可能是你的电脑死机的另一个原因。查看Linux日志文件中的线索。

编辑:由于您有wpa_supplicant填满日志文件,您应该检查文件系统的状态。完整的文件系统可能会导致系统挂起。如果您没有使用无线接口,请将其禁用。

+0

这是一个很好的解释。但为什么它会随着时间而不断增加。我怎样才能确定它不会导致系统冻结(发生在3-4天内)? –

+0

@NipunBatra你将不得不仔细看看系统。查看更新的答案。 –

+0

谢谢,已开始深入查看日志。增加了编辑2以突出可能与问题有关的一些有趣内容。也可以按照您的建议编写脚本进行监视 –