一个统计程序内存使用量的脚本

 

每隔5分钟统计一次指定程序的内存使用量,输出到标准输出。

安装 ps_mem

sudo apt install python3-pip
sudo pip3 install ps_mem

shell 脚本

#!/bin/bash

# 定义需要跟踪的程序列表
programs=("front8m_perception_node"
       	  "fisheyes_perception_node"
	  "decodec"
          "foxg_viz_front8m_od_res_node"
          "foxg_viz_front8m_resied_img_node"
  	  "foxg_viz_fisheyes_od_res_node"
  	  "foxg_viz_fisheyes_img_node")

while true; do
    # 遍历程序列表
    for program_name in "${programs[@]}"; do
        # 检查程序是否已经启动
        if pidof $program_name > /dev/null;then
	    pid=$(pidof $program_name | sed 's/ /,/g')
            # 获取内存使用信息
            mem_info=$(ps_mem -p $pid | grep $program_name)

            # 提取私有内存、共享内存和已使用内存的值
            private_mem=$(echo $mem_info | awk '{print $1}')
            shared_mem=$(echo $mem_info | awk '{print $4}')
            used_mem=$(echo $mem_info | awk '{print $7}')
	    prog_name=$(echo $mem_info | awk '{print $9$10}')
	else
            # 未启动的程序设置内存使用信息为0
            private_mem=0
            shared_mem=0
            used_mem=0
	    prog_name=$program_name
        fi

        # 获取当前时间
        current_time=$(date +"%Y-%m-%d %H:%M:%S")

        # 输出记录
        printf "%-19s | Program: %-50s | Private: %-10s | Shared: %-10s | Used: %-10s\n" "$current_time" "$prog_name" "$private_mem" "$shared_mem" "$used_mem"
    done

    # 等待5分钟
    sleep 300
done

几点解释:

  1. programs=(“prog1” “prog2”) 是需要跟踪的程序列表,可以根据需要修改。
  2. sed ‘s/ /,/g’ 是为了应对程序启动多个进程的情况。比如程序启动了两个进程,pidof 的输出是 “1234 5678”,而 ps_mem 要求的输入是 “1234,5678”。

配套的可视化数据python脚本

import matplotlib.pyplot as plt

def plot(num_progs: int):
    # 存储每个程序的内存使用量
    programs = {}

    # 读取文本文件
    with open('memory_log.txt', 'r') as file:
        for i, line in enumerate(file):
            # 解析每行的信息
            parts = line.strip().split('|')
            # time = parts[0].strip().split()[1].strip()[:-3]  # 提取小时和分钟部分
            time = i // num_progs
            program = parts[1].strip().split(':')[1].strip()
            private = float(parts[2].strip().split(':')[1].strip())
            shared = float(parts[3].strip().split(':')[1].strip())
            used = float(parts[4].strip().split(':')[1].strip())

            # 添加到程序字典中
            if program not in filtered_program:
                if program not in programs:
                    programs[program] = {'time': [], 'private': [], 'shared': [], 'used': []}
                programs[program]['time'].append(time)
                programs[program]['private'].append(private)
                programs[program]['shared'].append(shared)
                programs[program]['used'].append(used)

    # 创建包含三个子图的网格
    fig, axes = plt.subplots(1, 3, figsize=(12, 4))

    # 绘制Private内存使用量折线图
    ax1 = axes[0]
    for program, data in programs.items():
        ax1.plot(data['time'], data['private'], label=program)
    ax1.set_title('Private Memory Usage')
    ax1.set_xlabel('Time')
    ax1.set_ylabel('Memory (MB)')
    ax1.legend()

    # 绘制Shared内存使用量折线图
    ax2 = axes[1]
    for program, data in programs.items():
        ax2.plot(data['time'], data['shared'], label=program)
    ax2.set_title('Shared Memory Usage')
    ax2.set_xlabel('Time')
    ax2.set_ylabel('Memory (MB)')
    ax2.legend()

    # 绘制Used内存使用量折线图
    ax3 = axes[2]
    for program, data in programs.items():
        ax3.plot(data['time'], data['used'], label=program)
    ax3.set_title('Used Memory Usage')
    ax3.set_xlabel('Time')
    ax3.set_ylabel('Memory (MB)')
    ax3.legend()

    # 调整子图之间的间距
    plt.tight_layout()

    # 显示图表
    plt.show()

import sys
def main():
    num_progs = int(sys.argv[1])
    plot(num_progs)

if __name__ == "__main__":
    try:
        main()
    except Exception as e:
        print("error: " + str(e))
        print("调用示例:")
        print("python script.py [num_progs]")