psutil 4.0.0 以及如何获得 Python 中 真正的 进程内存和环境

发布于 2025-01-02 00:01:18 字数 11014 浏览 10 评论 0

现在,psutil 4.0.0 已经出来了,它带来了关于进程内存度量的一些有趣的消息。我将开门见山说明有什么新东西。

真正的 进程内存信息

确定一个过程真的使用多少内存并不是一件容易的事(见 这个这个 )。RSS(驻留集大小),这是大多数人平时靠的指标,它其实是会误导,因为它同时包含了进程独一无二的内存和与其他进程共享的内存。在分析方面更有趣的是,如果该进程即刻被终止,将释放的内存。在 Linux 的世界中,这被称为 USS(唯一集大小),并且这是在 psutil 4.0.0 引入(不仅适用于 Linux,也适用于 Windows 和 OSX)的主要功能。

USS 内存

USS(唯一集大小)是一个进程特有的内存,如果这个过程被终止,它将即刻被释放。在 Linux 上,这可以通过分析在 /proc/pid/smaps 中的所有“私有”块进行确定。Firefox 团队进一步对其进行推动,并且也成功地在 OSX 和 Windows 上做了同样的事。这是很棒的。psutil 新版本现在能够做同样的事:

>>> psutil.Process().memory_full_info()
pfullmem(rss=101990, vms=521888, shared=38804, text=28200, lib=0, data=59672, dirty=0, 
         uss=81623, pss=91788, swap=0)

PSS 和 swap

在 Linux 中,有两个也可以通过 /proc/pid/smaps 确定的额外指标:PSS 和 swap。PSS,又名“比例设置大小”,表示与其他进程共享的内存大小,它以这种方式进行计算: 总量最终在共享的进程之间平分 。也就是说,如果一个进程有 10 MB 都归自己(USS),并与另一个进程共享 10 MB,那么其 PSS 将是 15 MB。“swap”很简单,就是已经被交换到磁盘的内存量。使用 memory_full_info() 可以实现一个 像这样 的工具,类似于 Linux 上的 smem ,它提供了根据“USS”排序的进程列表。有趣的是,注意 RSS 和 USS 的区别:

~/svn/psutil$ ./scripts/procsmem.py
PID     User    Cmdline                            USS     PSS    Swap     RSS
==============================================================================
...
3986    giampao /usr/bin/python3 /usr/bin/indi   15.3M   16.6M      0B   25.6M
3906    giampao /usr/lib/ibus/ibus-ui-gtk3       17.6M   18.1M      0B   26.7M
3991    giampao python /usr/bin/hp-systray -x    19.0M   23.3M      0B   40.7M
3830    giampao /usr/bin/ibus-daemon --daemoni   19.0M   19.0M      0B   21.4M
20529   giampao /opt/sublime_text/plugin_host    19.9M   20.1M      0B   22.0M
3990    giampao nautilus -n                      20.6M   29.9M      0B   50.2M
3898    giampao /usr/lib/unity/unity-panel-ser   27.1M   27.9M      0B   37.7M
4176    giampao /usr/lib/evolution/evolution-c   35.7M   36.2M      0B   41.5M
20712   giampao /usr/bin/python -B /home/giamp   45.6M   45.9M      0B   49.4M
3880    giampao /usr/lib/x86_64-linux-gnu/hud/   51.6M   52.7M      0B   61.3M
20513   giampao /opt/sublime_text/sublime_text   65.8M   73.0M      0B   87.9M
3976    giampao compiz                          115.0M  117.0M      0B  130.9M
32486   giampao skype                           145.1M  147.5M      0B  149.6M

实现

要获得这些值(USS, PSS 和 swap),我们需要遍历珍格格进程地址空间。这通常需要更高的用户权限,并且比通过 Process.memory_info() 获得“正常”的内存度量慢得多,这可能就是为什么像 pstop 之类的工具显示 RSS/VMS 而不是 USS。非常感谢 Mozilla 团队,他们在 Windows 和 OSX 上都考虑到了这些,同时感谢 Eric Rahm,他为 psutil 把 PR 都放在一起了(见 #744 , #745#746 )。对于你们那些不使用 Python,但是像将代码移植到另一个语言上的人,下面是有趣的部分:

内存类型百分比

经过 重组进程内存 API 后,我决定添加一个新的 memtype 参数到 Process.memory_percent() 中。与此,它现在可以将一个指定的内存类型(不仅仅是 RSS)与总物理内存进行比较了。例如:

>>> psutil.Process().memory_percent(memtype='pss')
0.06877466326787016

进程环境变量

psutil 4.0.0 中第二大改进是确定 进程环境变量 的能力。这将开启进程识别和监控技术的有趣的可能。例如,有人会通过传递某些自定义环境变量来启动一个进程,然后遍历所有进程来找到感兴趣的那个进程(并弄清楚它是否正在运行):

import psutil
for p in psutil.process_iter():
    try:
        env = p.environ()
    except psutil.Error:
        pass
    else:
        if 'MYAPP' in env:
            ...

进程环境变量是一个 长期存在的问题 , (在 2009 年) 因为 Windows 实现仅对当前进程有效,所以我放弃实现。Frank Benkstein 解决了这个问题 ,所以现在对于所有进程,都可以在 Linux, Windows 和 OSX 上确定进程变量(当然,你仍然可以碰到其他用户拥有的进程的 AccessDenied ):

>>> import psutil
>>> from pprint import pprint as pp
>>> pp(psutil.Process().environ())
{...
 'CLUTTER_IM_MODULE': 'xim',
 'COLORTERM': 'gnome-terminal',
 'COMPIZ_BIN_PATH': '/usr/bin/',
 'HOME': '/home/giampaolo',
 'PWD': '/home/giampaolo/svn/psutil',
  }
>>>

必须指出的是,所得到的字典通常不反映进程开始之后所做的更改(例如 os.environ['MYAPP'] = '1' )。同样,对于任何有兴趣在其他语言中这样做的人,这里是有趣的部分:

扩展磁盘 IO 统计信息

psutil.disk_io_counters() 已经被扩展为报告 Linux 和 FreeBSD 上的附加度量:

  • busy_time ,这是进行实际 I/O 花费的时间(毫秒)。
  • read_merged_countwrite_merged_count (只用于 Linux),这是合并读数和合并写数(见 iostats 文档)

有了这些新的度量,就有可能有 实际磁盘利用率 的一个更好的表示,类似于 Linux 上的 iostat 命令。

OS 常量

Given the increasing number of platform-specific metrics I added a new set of 由于特定于平台的度量数量的增加,我添加了一套新的 常量 来快速区分你是在什么平台上: psutil.LINUX , psutil.WINDOWS 等等。

主要 bug 修复

  • #734 : 在 Python 3 上,对于 name() , cwd() , exe() , cmdline()open_files() 方法,无效的 UTF-8 数据不能正确地被处理,从而导致 UnicodeDecodeError 。这影响到所有平台。现在 surrogateescape 错误处理成千被用作替换损坏的数据的解决方法。
  • #761 : [Windows] psutil.boot_time() 在 49 天后不会再变成 0。
  • #767 : [Linux] 在 2.6 内核上,disk_io_counters() 可能会引发 ValueError 错误,而在 2.4 内核上可能会崩溃。
  • #764 : 现在可以在 NetBSD-6.X 上编译 psutil 了。
  • #704 : 现在可以在 Solaris sparc 上编译 psutil 了。

完整的 bug 修复列表在 这里

移植代码

4.0.0 作为一个主要版本,我抓住机会(稍微的)修改/破坏某些 API。

  • Process.memory_info() 不再只返回一个 (rss, vms) 命名元组。相反,它会返回一个可变长度,基于平台修改的命名元组(虽然 rssvms 总是存在,在 Windows 上也是)。基本上,它返回与老的 process_memory_info_ex() 相同的结果。这不应该破坏你已有的代码,触发你正在使用 "rss, vms = p.memory_info()"
  • 同时, process_memory_info_ex() 现已启用。该方法作为 memory_info() 的别名仍然存在,它会发出一个弃用警告。
  • psutil.disk_io_counters() 在 Linux 上返回两个额外的字段,在 FreeBSD 上返回一个额外的字段。
  • NetBSD 和 OpenBSD 上的 psutil.disk_io_counters() 不再返回 write_countread_count 度量,因为内核不再提供它们(取而代之,我们返回忙绿时间)。我也不希望这是一个大问题,因为 OpenBSD 支持是非常近的。

最后说明,以及找工作

好了,就是这些了。(译者:后面是原文作者的一堆找工作的信息,有兴趣的请到原文上查看,这里就不进行翻译了)

外部链接

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

物价感观

暂无简介

文章
评论
27 人气
更多

推荐作者

5576443447

文章 0 评论 0

酒几许

文章 0 评论 0

xiaolangfanhua

文章 0 评论 0

好久不见√

文章 0 评论 0

盗心人

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文