统计exe进程性能指标

# !/usr/bin/python
# -*- coding: utf-8 -*-
"""
@File    :  tools_perf_monitor.py
@Time    :  2022/2/26 11:50
@Author  :  HuangJunYi
@Version :  1.0
@Desc    :  None
"""
import os
import re
import time
import psutil
# import win32api
from ctypes import windll
from datetime import datetime
from numpy.core import mean
from pyecharts.charts import Line, Tab, Bar
import pyecharts.options as opts
import sys
sys.path.append("D:\perftestframework")
from Bases import bases_params
from Bases.bases_handlers import PsutilUtils



def tools_checkPerfMonitorVersion(process_name):
    """
    获取当前监控客户端版本号
    :return:
    """
    # file_ver_dict = win32api.GetFileVersionInfo(ConfigUtils().utils_get_config(bases_params.config_path, 'getXDVersion', 'xd_path'), os.sep)
    # 主版本号 / 次版本号,备注截取于 Win32API 参考手册
    # 对于所有平台,低位字包含 Windows 的版本号,该字的低位字节以十六进制表示法指定主版本号,高位字节以十六进制表示法指定次版本(版本号)
    # FileVersionLS / FileVersionMS 指文件版本
    # product_ver_ms = file_ver_dict['ProductVersionMS']
    # product_ver_ls = file_ver_dict['ProductVersionLS']
    # current_ver = '%d.%d.%d.%d' % (win32api.HIWORD(product_ver_ms), win32api.LOWORD(product_ver_ms), win32api.HIWORD(product_ver_ls), win32api.LOWORD(product_ver_ls))
    current_ver = ""
    if process_name == "tdxw.exe":
        current_ver = "通达信进程"
    elif process_name == "xiadan.exe":
        current_ver = "下单还原进程"
    elif process_name == "hexin.exe":
        current_ver = "下单精简进程"
    return current_ver


def tools_perfMonitor(process_name, cases_name, print_interval=1, time_wait=30):
    """
    性能监控
    :param process_name: 目标进程名称
    :param cases_name: 生成 log 的名称
    :param print_interval: 打印监控数据间隔
    :param time_wait: 设置了一个等待时间,期间内如果可以获取到目标进程,则继续监控,否则监控结束
    :return:
    """

    # 获取进程的标识符,默认False
    process_flag = False
    # 动态获取进程号,获取最长时间为:time_wait,期间内如果可以获取到目标进程,退出循环,代码继续往下执行
    now_data = time.time()
    while time.time() <= now_data + time_wait:
        if PsutilUtils.utils_get_process_id(process_name):
            # 获取进程号时,设置flag为True
            process_flag = True
            break
        else:
            time.sleep(0.5)
            continue

    # 若获取当前进程
    if process_flag:
        proc = psutil.Process(PsutilUtils.utils_get_process_id(process_name))
        while True:
            # 打印监控数据间隔
            time.sleep(print_interval)
            # 若获取进程,则开始监控,并写入数据
            if PsutilUtils.utils_get_process_id(process_name) is not None:
                # 工作设置内存
                work_setup_memory = proc.memory_info().rss / 1024
                # 提交大小内存
                commit_size_memory = proc.memory_info().private / 1024
                # 占用总内存百分比
                perc_of_total_memory = round(float(proc.memory_percent()), 1)
                # 进程句柄数
                proc_handles = proc.num_handles()
                # CPU 使用率
                cpu_usage = proc.cpu_percent()
                # GDI 对象
                gdi_object = windll.user32.GetGuiResources(windll.kernel32.OpenProcess(5432, 0, PsutilUtils.utils_get_process_id(process_name)), 0)
                windll.kernel32.CloseHandle(windll.kernel32.OpenProcess(5432, 0, PsutilUtils.utils_get_process_id(process_name)))
                # IO 读
                io_read = proc.io_counters().read_count
                # IO 写
                io_write = proc.io_counters().write_count
                if os.path.exists(bases_params.perf_log_path + tools_checkPerfMonitorVersion(process_name)):
                    pass
                else:
                    os.makedirs(bases_params.perf_log_path + tools_checkPerfMonitorVersion(process_name))
                with open(bases_params.perf_log_path + tools_checkPerfMonitorVersion(process_name) + '/' + cases_name + '.log', 'a') as f:
                    f.write('时间: {}, 工作设置内存: {}, 提交大小内存: {}, 占用总内存百分比: {}, 进程句柄数: {}, CPU 使用率: {}, GDI 对象: {}, IO读: {}, IO写:{} \n'.format(datetime.now(), work_setup_memory, commit_size_memory, perc_of_total_memory, proc_handles, cpu_usage, gdi_object, io_read, io_write))
                    f.close()

            # 进程再次消失时,退出监控
            elif PsutilUtils.utils_get_process_id(process_name) is None:
                break


def tools_perfDatasClean(ver, cases_name):
    """
    性能数据清洗
    :param ver: 版本号
    :param cases_name: 生成 log 的名称
    :return:
    """
    # work_setup_memory: 工作设置内存
    # commit_size_memory: 提交大小内存
    # perc_of_total_memory: 占用总内存百分比
    # proc_handles: 进程句柄数
    # cpu_usage: CPU 使用率
    # gdi_object: GDI 对象

    work_setup_memory = []
    commit_size_memory = []
    perc_of_total_memory = []
    proc_handles = []
    cpu_usage = []
    gdi_object = []
    with open(bases_params.perf_log_path + ver + '\\' + cases_name + '.log', 'r') as f:
        for line in f.readlines():
            work_setup_memory.append(''.join(re.findall(r'工作设置内存: (.*), 提交大小内存', line)))
            commit_size_memory.append(''.join(re.findall(r'提交大小内存: (.*), 占用总内存百分比', line)))
            perc_of_total_memory.append(''.join(re.findall(r'占用总内存百分比: (.*), 进程句柄数', line)))
            proc_handles.append(''.join(re.findall(r'进程句柄数: (.*), CPU 使用率', line)))
            cpu_usage.append(''.join(re.findall(r'CPU 使用率: (.*), GDI 对象', line)))
            gdi_object.append(''.join(re.findall(r'GDI 对象: (.*), IO读', line)))
        datas = {"version": ver, "工作设置内存": work_setup_memory, "提交大小内存": commit_size_memory, "占用总内存百分比": perc_of_total_memory, "进程句柄数": proc_handles, "CPU 使用率": cpu_usage, "GDI 对象": gdi_object}
    return datas


def tools_generatorChartsDatas(ver, cases_name):
    """
    生成 charts 图数据
    :param ver: 版本号(列表形式)
    :param cases_name: 生成 log 的名称
    :return:
    """
    charts_datas = []
    for ver in ver:
        charts_datas.append(tools_perfDatasClean(ver, cases_name))
    return charts_datas


def tools_generatorLineCharts(ver, cases_name, perf_types):
    """
    生成性能变化趋势图
    :param ver: 版本号(列表)
    :param cases_name: log 名称
    :param perf_types: 性能指标
    :return:
    """
    # 需要根据所取y轴数据取最大值来作x轴的数据
    x = [i for i in range(1, max(len(datas[perf_types]) for datas in tools_generatorChartsDatas(ver, cases_name)))]
    line = (
        Line()
        .add_xaxis(x)
        .set_global_opts(
            xaxis_opts=opts.AxisOpts(name='Times \n\n 时间间隔:1s'),
            yaxis_opts=opts.AxisOpts(name='登录-单笔-批量-撤单-退出 \n\n Size')
        )
    )
    for datas in tools_generatorChartsDatas(ver, cases_name):
        _line = (
            Line()
            .add_xaxis(x)
            .add_yaxis(datas['version'], datas[perf_types], is_symbol_show=False, is_smooth=True, is_connect_nones=True)
        )
        line.overlap(_line)
    return line


def tools_generatorBarCharts(ver, cases_name, perf_types):
    bar = (
        Bar()
        .add_xaxis(['MAX', 'MIN', 'AVG'])
    )
    for datas in tools_generatorChartsDatas(ver, cases_name):
        params = []
        for x in datas[perf_types]:
            if x != '' and x != '0.0' and x != '0':
                params.append(x)
        MAX = max([float(x) for x in params])
        MIN = min([float(x) for x in params])
        AVG = round(mean([float(x) for x in params]), 2)
        _bar = (
            Bar()
            .add_xaxis(['MAX', 'MIN', 'AVG'])
            .add_yaxis(datas['version'], [MAX, MIN, AVG], gap='0%', bar_width='20%')
        )
        bar.overlap(_bar)
    return bar


if __name__ == '__main__':
    # process_name = "tdxw.exe"
    # cases_name = "wt"
    # process_name = "hexin.exe"
    # cases_name = "wt"
    # process_name = "xiadan.exe"
    # cases_name = "wt"
    # tools_perfMonitor(process_name, cases_name)

    tab = Tab()
    for types in ['工作设置内存', '提交大小内存', '占用总内存百分比', '进程句柄数', 'CPU 使用率', 'GDI 对象']:
        # 生成 charts 图时,仅需要修改这里的参数即可
        # 折线图
        tab.add(tools_generatorLineCharts(['通达信进程', '下单还原进程', '下单精简进程'], 'wt', types), types)
        # 柱形图
        # tab.add(tools_generatorBarCharts(['通达信进程', '下单还原进程', '下单精简进程'], 'wt', types), types)
    if os.path.exists(bases_params.perf_img_path):
        tab.render(bases_params.perf_img_path + '\\' + 'TDXvsTHSzw.html')
    else:
        os.makedirs(bases_params.perf_img_path)
        tab.render(bases_params.perf_img_path + '\\' + 'TDXvsTHSzw.html')

你可能感兴趣的:(Python,性能测试,python,windows,numpy)