<svg width="80" height="80" viewBox="0 0 250 250" style="fill: #222; color: #fff; position: absolute; top: 0; border: 0; right: 0;" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg>

Oscillo:利用psutil监控进程的cpu和内存负载

demo

如果使用过glances,如果有一颗geek的心的话,一定会觉得不但酷炫而且十分实用。不过如果想观察一个程序从运行开始到结束的cpu占用率怎么办?好办,利用python的psutil异步观察就行。

介绍一下放在github上的一个项目: oscillo

使用方式

使用方式很简单,直接 pip install oscillo即可安装使用.

命令行参数的格式是 "<name>: <command [args]>"

  • name: 命令行的别名/id (任意字符串),当--commands/-c参数指定多个命令时,该值将作为命令的唯一标识,不可重复
  • command [args]: 需要测试资源消耗的命令,比如 gzip file.ext

示例如下,监控gzip压缩一个文件时耗费的cpu、memory和时间:

1
oscillo -c 'gzip: gzip file.ext' -o output-file
  • -c 代表将执行一个linux cmd 命令。参数后面可以跟以空格隔开的多个参数

  • -o 结果输出文件:

命令执行完成后,会在当前目录下生成一个<output-file>.log 文件。文本结构是json 格式. 数据结构如下

1
2
3
4
5
6
7
{
"test": {
"elapsed": 0.022143125534057617, //总执行时间
"cpu": [],
"memory": []
}
}

同时会产生一个<output-file>.png文件,<output-file>-o参数指定,默认值为metrix

在控制台上,oscillo会打印summary信息,其中包含命令的耗时、最大内存使用、最大cpu使用、退出码等在控制台上,oscillo会打印summary信息,其中包含命令的耗时、最大内存使用、最大cpu使用、退出码等

如果想对比多个命令对资源的消耗,可以使用 -c/--commands 选项指定多条命令, e.g.:

对比gziptar命令对资源的消耗:

1
oscillo -c 't1: gzip file.ext'  't2: tar czf target.tar.gz file1' -o output

效果如下:

demo

demo

实现原理

这个工具的原型,来自于一次为了对比几种客户端性能而写的一个脚本,它的原理就是:

  • 在程序中启动一个子进程,获取进程id
  • 通过psutil观察该进程,每隔一段时间记录一次cpu和内存的负载
  • 通过matplotlib画图

说一下其中碰到的一个坑:欲监控的子进程A在内部调用了另一个耗资源的子进程B,但是psutil只能观察到子进程A的资源消耗情况,粗暴的解决办法就是:观察全局的资源消耗情况:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Stopwatch(object):

def __init__(self, pid):
self.__is_run = False
self.__start_time = 0
self.__elapsed_times = 0
self.memory_percent = []
self.cpu_percent = []
self.pid = pid

def start(self):
if self.__is_run:
return False
self.__is_run = True
self.__start_time = time.time()

if self.pid > 0:
p = psutil.Process(self.pid)
else:
p = psutil
p.memory_percent = lambda: p.virtual_memory().percent
while self.__is_run:
try:
self.cpu_percent.append(p.cpu_percent(1))
self.memory_percent.append(p.memory_percent())
except psutil.NoSuchProcess:
break

@property
def elapsed(self):

if self.__is_run:
return self.__elapsed_times + time.time() - self.__start_time
return self.__elapsed_times

def stop(self):
self.__elapsed_times = self.elapsed
self.__is_run = False

BTW

当前的功能比较简单,可能有很多东西没用想到,欢迎使用和完善

git仓库: oscillo