jiyuhang пре 3 месеци
комит
e5b5a4a94b

+ 5 - 0
.idea/.gitignore

@@ -0,0 +1,5 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
+# 基于编辑器的 HTTP 客户端请求
+/httpRequests/

+ 6 - 0
.idea/inspectionProfiles/profiles_settings.xml

@@ -0,0 +1,6 @@
+<component name="InspectionProjectProfileManager">
+  <settings>
+    <option name="USE_PROJECT_PROFILE" value="false" />
+    <version value="1.0" />
+  </settings>
+</component>

+ 8 - 0
.idea/listen_py.iml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="PYTHON_MODULE" version="4">
+  <component name="NewModuleRootManager">
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="jdk" jdkName="pytest" jdkType="Python SDK" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>

+ 7 - 0
.idea/misc.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="Black">
+    <option name="sdkName" value="torch" />
+  </component>
+  <component name="ProjectRootManager" version="2" project-jdk-name="pytest" project-jdk-type="Python SDK" />
+</project>

+ 8 - 0
.idea/modules.xml

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/listen_py.iml" filepath="$PROJECT_DIR$/.idea/listen_py.iml" />
+    </modules>
+  </component>
+</project>

+ 3 - 0
config.json

@@ -0,0 +1,3 @@
+{
+  "test_script_dir": "./test/test_script.py"
+}

+ 148 - 0
integrate_results.py

@@ -0,0 +1,148 @@
+# integrate_results.py
+import pstats
+import json
+import argparse
+from datetime import datetime
+import matplotlib.pyplot as plt
+import pandas as pd
+import os
+
+def parse_cprofile_data(cprofile_file, top_K=20):
+    """解析cProfile数据"""
+    try:
+        stats = pstats.Stats(cprofile_file)  # pstats是专门查看cProfile结果的工具库
+        all_functions = list(stats.stats.items())
+        # 使用 lambda 函数指定排序关键字为 x[1][3],即每个数据项的累计时间
+        sorted_functions = sorted(all_functions, key=lambda x: x[1][3], reverse=True)
+
+        # 提取前top_k个最耗时的函数
+        top_functions = []
+        for func, (cc, nc, tt, ct, callers) in sorted_functions[:top_K]:
+            top_functions.append({
+                'function': str(func),
+                'call_count': cc,
+                'total_time': tt,
+                'cumulative_time': ct
+            })
+
+        return {
+            'type': 'cprofile',
+            'points': top_functions,
+            'num': len(top_functions)
+        }
+    except Exception as e:
+        return {'type': 'cprofile', 'error': str(e)}
+
+def parse_memory_profile(memory_file):
+    """解析memory_profiler数据"""
+    try:
+        # 读取内存数据文件
+        with open(memory_file, 'r') as f:
+            lines = f.readlines()
+
+        memory_data = []
+        for line in lines:
+            if line.startswith('MEM'):
+                parts = line.strip().split()
+                if len(parts) >= 3:
+                    try:
+                        memory = float(parts[1])  # 单位MB
+                        timestamp = float(parts[2])
+                        memory_data.append({'timestamp': timestamp, 'memory': memory})
+                    except ValueError:
+                        continue
+
+        return {
+            'type': 'memory_profile',
+            'points': memory_data,  # 所有数据点
+            'num': len(memory_data),  # 数量
+            'peak_memory': max([d['memory'] for d in memory_data]) if memory_data else 0
+        }
+    except Exception as e:
+        return {'type': 'memory_profile', 'error': str(e)}
+
+def parse_pyspy_data(flamegraph_file):
+    """解析py-spy火焰图数据(简单分析)"""
+    try:
+        # 火焰图是SVG文件,这里只是做基本检查
+        file_size = os.path.getsize(flamegraph_file)
+
+        return {
+            'type': 'pyspy_flamegraph',
+            'file_size_bytes': file_size,
+            'status': 'generated'
+        }
+    except Exception as e:
+        return {'type': 'pyspy_flamegraph', 'error': str(e)}
+
+def parse_psutil_data(psutil_file):
+    """解析psutil监控数据"""
+    # 如果有具体的psutil输出文件格式,可以在这里添加解析逻辑
+    try:
+        data = pd.read_csv(psutil_file).loc[:,['pid','now_time', 'cpu_pct', 'rss', 'vms','mem_pct','disk_read','disk_write','sys_net_recv','sys_net_send']]
+        # 占位符,根据实际psutil输出格式调整
+        collected = data.to_dict('records')
+
+        return {
+            'type': 'psutil',
+            'points': collected,
+            'num':len(collected)
+        }
+    except Exception as e:
+        return {'type': 'psutil', 'error': str(e)}
+
+def integrate_results(cprofile_file, memory_file, flamegraph_file, psutil_file, output_file):
+    """整合所有分析结果"""
+    integrated_data = {
+        'timestamp': datetime.now().isoformat(),
+        'analysis_results': {}
+    }
+
+    # 解析各个工具的输出
+    if cprofile_file:
+        integrated_data['analysis_results']['cprofile'] = parse_cprofile_data(cprofile_file)
+
+    if memory_file:
+        integrated_data['analysis_results']['memory_profile'] = parse_memory_profile(memory_file)
+
+    if flamegraph_file:
+        integrated_data['analysis_results']['pyspy_flamegraph'] = parse_pyspy_data(flamegraph_file)
+
+    if psutil_file:
+        integrated_data['analysis_results']['psutil'] = parse_psutil_data(psutil_file)
+
+    # 保存整合结果
+    with open(output_file, 'w', encoding='utf-8') as f:
+        json.dump(integrated_data, f, indent=2, ensure_ascii=False)
+
+    print(f"整合报告已保存至: {output_file}")
+    return integrated_data
+
+def main():
+    parser = argparse.ArgumentParser(description='整合Python性能分析结果')
+    parser.add_argument('--cprofile', default='./cprofile_output.prof',help='cProfile输出文件路径')
+    parser.add_argument('--memory', default='./mprofile_output.dat', help='memory_profiler输出文件路径')
+    parser.add_argument('--flamegraph',default='./pyspy_output.svg', help='py-spy火焰图文件路径')
+    parser.add_argument('--psutil',default='./output.csv', help='psutil监控数据文件路径')
+    parser.add_argument('--output', default='integrated_report.json', help='整合报告输出路径')
+
+    args = parser.parse_args()
+
+    result = integrate_results(
+        args.cprofile,
+        args.memory,
+        args.flamegraph,
+        args.psutil,
+        args.output
+    )
+
+    # 打印摘要信息
+    print("\n=== 性能分析整合报告摘要 ===")
+    for tool, data in result['analysis_results'].items():
+        if 'error' in data:
+            print(f"{tool}: 错误 - {data['error']}")
+        else:
+            print(f"{tool}: 成功处理")
+
+if __name__ == "__main__":
+    main()

+ 416 - 0
main.sh

@@ -0,0 +1,416 @@
+#!/bin/bash
+
+# 性能测试脚本,用于顺序执行多种性能分析工具
+# 颜色定义
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+BLUE='\033[0;34m'
+NC='\033[0m' # No Color
+
+# 默认参数
+RESULT_DIR="results"
+TEST_SCRIPT=""  # 待测试的脚本
+PSUTIL_SCRIPT="monitor_util.py"  # 监测工具脚本
+INTEGRATED_SCRIPT="integrate_results.py"  # 融合工具脚本
+CPROFILE_OUTPUT="$RESULT_DIR/cprofile_output.prof"  # cProfile 结果文件
+MEMORY_PROFILE_OUTPUT="$RESULT_DIR/mprofile_output.dat"  # memory_profiler输出文件
+MEMORY_PLOT_OUTPUT="$RESULT_DIR/mprofile_memory_plot.png"  # memory_profiler 绘制的曲线图
+FLAMEGRAPH_OUTPUT="$RESULT_DIR/pyspy_output.svg"  # py-spy 输出文件
+PSUTIL_OUTPUT="$RESULT_DIR/psutil_output.csv"  # psutil 输出文件
+INTEGRATED_REPORT="$RESULT_DIR/performance_analysis_report.json"  # 融合结果文件
+
+# 日志函数
+log_info() {
+    echo -e "${BLUE}[INFO]${NC} $1"
+}
+
+log_success() {
+    echo -e "${GREEN}[SUCCESS]${NC} $1"
+}
+
+log_warning() {
+    echo -e "${YELLOW}[WARNING]${NC} $1"
+}
+
+log_error() {
+    echo -e "${RED}[ERROR]${NC} $1"
+}
+
+# 显示标题
+show_header() {
+    echo "========================================="
+    echo "Python脚本性能分析工具链"
+    echo "========================================="
+    sleep 2
+}
+
+# 显示步骤标题
+show_step() {
+    echo ""
+    echo "-----------------------------------------"
+    echo "$1"
+    echo "-----------------------------------------"
+}
+
+# 检查脚本文件是否存在
+check_script_exists() {
+    if [ -f "config.json" ]; then
+        TEST_SCRIPT=$(python -c "
+import json
+try:
+    with open('config.json', 'r') as f:
+        config = json.load(f)
+        print(config.get('test_script_dir', ''))
+except Exception as e:
+    print('')
+" 2>/dev/null)
+
+        if [ -n "$TEST_SCRIPT" ]; then
+            log_info "从 config.json 读取测试脚本路径: $TEST_SCRIPT"
+        else
+            log_warning "config.json 中未找到有效的 test_script_dir 配置"
+            return 1
+        fi
+    else
+        log_warning "未找到 config.json 配置文件"
+        return 1
+    fi
+
+    if [ ! -f "$TEST_SCRIPT" ]; then
+        log_error "测试脚本 $TEST_SCRIPT 不存在"
+        return 1
+    fi
+    sleep 2
+    return 0
+}
+# 创建结果保存目录
+mk_dir(){
+    if [ ! -d "$RESULT_DIR" ]; then
+        mkdir -p "$RESULT_DIR"
+        log_info "创建结果保存目录: $RESULT_DIR"
+    else
+        log_info "使用现有结果保存目录: $RESULT_DIR"
+    fi
+}
+
+# 1. 使用cProfile进行性能分析
+run_cprofile() {
+    show_step "步骤 1: 使用 cProfile 进行性能分析"
+    log_info "准备对 $TEST_SCRIPT 进行性能分析..."
+    
+    # 确保使用绝对路径
+    PROFILE_ABS_PATH="$(pwd)/$CPROFILE_OUTPUT"
+    
+    if python -m cProfile -o "$PROFILE_ABS_PATH" "$TEST_SCRIPT"; then
+        log_success "cProfile 分析完成,结果保存至 $PROFILE_ABS_PATH"
+        return 0
+    else
+        log_error "cProfile 分析失败"
+        return 1
+    fi
+}
+
+# 3. 使用memory_profiler分析内存使用情况
+run_memory_profiler() {
+    show_step "步骤 3: 使用 memory_profiler 分析内存使用情况"
+    
+    # 检查是否安装了memory_profiler
+    if ! command -v mprof &> /dev/null; then
+        log_warning "未找到 memory_profiler (mprof),尝试安装..."
+        if pip3 install memory-profiler -i https://pypi.tuna.tsinghua.edu.cn/simple; then
+            log_success "memory_profiler 安装成功"
+            echo "适配安装matplotlib: "
+            conda install matplotlib
+        else
+            log_error "memory_profiler 安装失败"
+            return 1
+        fi
+    fi
+
+    # 运行内存分析
+    if command -v mprof &> /dev/null; then
+        if mprof run --output "$MEMORY_PROFILE_OUTPUT" "$TEST_SCRIPT"; then
+            log_success "memory_profiler 分析完成,结果保存至 $MEMORY_PROFILE_OUTPUT"
+            
+            # 绘制内存占用曲线
+            log_info "绘制内存占用曲线"
+            if MPLBACKEND=Agg mprof plot --flame  "$MEMORY_PROFILE_OUTPUT" -o "$MEMORY_PLOT_OUTPUT"; then
+                log_success "绘制完成,结果保存至 $MEMORY_PLOT_OUTPUT"
+            else
+                log_error "绘制失败"
+            fi
+        else
+            log_error "memory_profiler 分析失败"
+        fi
+    else
+        log_warning "无法安装 memory_profiler,跳过内存分析步骤"
+    fi
+}
+
+# 2. 使用py-spy记录性能数据
+run_py_spy() {
+    show_step "步骤 2: 使用 py-spy record 进行性能分析"
+
+    # 检查是否安装了py-spy
+    if ! command -v py-spy &> /dev/null; then
+        log_warning "未找到 py-spy ,尝试安装..."
+        if pip3 install py-spy -i https://pypi.tuna.tsinghua.edu.cn/simple; then
+            log_success "py-spy 安装成功"
+        else
+            log_error "py-spy 安装失败"
+            return 1
+        fi
+    fi
+
+    # 再次检查是否安装成功
+    if ! command -v py-spy &> /dev/null; then
+        log_error "py-spy 安装失败"
+        return 1
+    fi
+
+    # 根据操作系统类型选择合适的py-spy参数,需要统计子线程和C拓展
+    if [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "win32" ]]; then
+        # Windows环境下使用--nonblocking选项
+        log_info "Windows环境下使用--nonblocking选项"
+        PYSPY_CMD="py-spy record -o $FLAMEGRAPH_OUTPUT --duration 35 --native --subprocesses --nonblocking -- python $TEST_SCRIPT"
+    elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
+        # Linux环境下使用sudo运行
+        log_info "Linux环境下使用sudo运行py-spy"
+        PYSPY_CMD="sudo env \"PATH=\$PATH\" py-spy record -o $FLAMEGRAPH_OUTPUT --duration 35 --native --subprocesses -- python $TEST_SCRIPT"
+    else
+        # 其他Unix系统使用默认选项
+        PYSPY_CMD="py-spy record -o $FLAMEGRAPH_OUTPUT --duration 35 --native --subprocesses -- python $TEST_SCRIPT"
+    fi
+    
+    log_info "执行命令: $PYSPY_CMD"
+    eval "$PYSPY_CMD"
+    PYSPY_PID=$!
+    if wait $PYSPY_PID; then
+        log_success "py-spy record 分析完成,火焰图保存至 $FLAMEGRAPH_OUTPUT"
+        return 0
+    else
+        log_error "py-spy record 分析失败"
+        if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+            log_warning "提示: 可能需要管理员权限,请使用 'sudo ./$0' 运行此脚本"
+        fi
+        return 1
+    fi
+}
+# 4. 使用psutil获取进程信息
+run_psutil() {
+  show_step "步骤 4: 使用 psutil 获取进程信息"
+  
+  # 检查是否安装了psutil
+  if ! python -c "import psutil" &> /dev/null; then
+    log_warning "未找到 psutil ,尝试安装..."
+    if pip3 install psutil -i https://pypi.tuna.tsinghua.edu.cn/simple; then
+      log_success "psutil 安装成功"
+    else
+      log_error "psutil 安装失败"
+      return 1
+    fi
+  fi
+
+  # 在后台运行test_script.py并获取其PID
+  log_info "在后台启动 $TEST_SCRIPT ..."
+  python "$TEST_SCRIPT" &
+  TEST_PID=$!
+  
+  # 等待一段时间确保进程已经完全启动
+  sleep 2
+  
+  # 验证进程是否仍在运行
+  if ! kill -0 $TEST_PID 2>/dev/null; then
+    log_error "测试脚本启动失败"
+    return 1
+  fi
+  
+  log_info "测试脚本 PID: $TEST_PID"
+  
+  # 使用monitor.py监控该进程
+  log_info "开始监控进程资源使用情况..."
+  if [[ "$OSTYPE" == "linux-gnu"* ]]; then
+      # Linux环境下使用sudo运行monitor.py
+      sudo env "PATH=$PATH" python "$PSUTIL_SCRIPT" --pid $TEST_PID --output "$PSUTIL_OUTPUT" &
+  else
+      python "$PSUTIL_SCRIPT" --pid $TEST_PID --output "$PSUTIL_OUTPUT" &
+  fi
+  MONITOR_PID=$!
+  
+  # 等待test_script.py执行完成
+  wait $TEST_PID
+  sleep 4
+  log_success "测试脚本执行完成"
+  # 终止monitor.py
+  kill $MONITOR_PID 2>/dev/null || true
+  
+  log_success "资源监控完成,结果保存至 $PSUTIL_OUTPUT"
+}
+
+# 自动打开SVG文件
+open_svg_file() {
+    if [ -f "$FLAMEGRAPH_OUTPUT" ]; then
+        log_info "正在尝试在浏览器中打开火焰图..."
+        
+        # 检测是否在WSL环境中
+        if grep -qE "(Microsoft|WSL)" /proc/version 2>/dev/null; then
+            # WSL环境 - 使用PowerShell打开
+            log_info "检测到WSL环境,使用PowerShell打开文件"
+            if powershell.exe -Command "Start-Process '$(wslpath -w "$(pwd)/$FLAMEGRAPH_OUTPUT")'" 2>/dev/null; then
+                log_success "SVG文件已在Windows默认应用中打开"
+                return 0
+            elif cmd.exe /c "start $(wslpath -w "$(pwd)/$FLAMEGRAPH_OUTPUT")" 2>/dev/null; then
+                log_success "SVG文件已在Windows默认应用中打开"
+                return 0
+            else
+                log_warning "无法在Windows主机上打开文件,请手动打开 $FLAMEGRAPH_OUTPUT"
+            fi
+        elif command -v xdg-open >/dev/null 2>&1; then
+            # 标准Linux环境
+            if xdg-open "$FLAMEGRAPH_OUTPUT"; then
+                log_success "SVG文件已在默认应用中打开"
+                return 0
+            else
+                log_warning "无法使用xdg-open打开文件"
+            fi
+        elif command -v gnome-open >/dev/null 2>&1; then
+            if gnome-open "$FLAMEGRAPH_OUTPUT"; then
+                log_success "SVG文件已在默认应用中打开"
+                return 0
+            else
+                log_warning "无法使用gnome-open打开文件"
+            fi
+        else
+            log_warning "找不到合适的打开命令,请手动在浏览器中打开 $FLAMEGRAPH_OUTPUT"
+        fi
+    fi
+    return 1
+}
+
+# 自动打开prof文件
+open_prof_file() {
+  # 检查snakeviz是否存在,不存在就尝试自动安装
+  if [ -f "$CPROFILE_OUTPUT" ]; then
+    log_info "自动打开cProfile分析结果"
+    if ! command -v snakeviz &> /dev/null; then
+      log_warning "未找到snakeviz,尝试安装..."
+      if pip3 install snakeviz -i https://pypi.tuna.tsinghua.edu.cn/simple; then
+        log_success "snakeviz 安装成功"
+      else
+        log_error "snakeviz 安装失败"
+        return 1
+      fi
+    fi
+
+    if command -v snakeviz &> /dev/null; then
+      log_info "正在尝试使用snakeviz打开prof文件..."
+      if snakeviz "$CPROFILE_OUTPUT"; then
+        log_success "prof文件浏览完成"
+        return 0
+      else
+        log_warning "无法使用snakeviz打开prof文件"
+      fi
+    else
+      log_warning "snakeviz未安装,请手动打开 $CPROFILE_OUTPUT"
+    fi
+  else
+    log_error "$CPROFILE_OUTPUT 文件不存在"
+  fi
+   return 1
+}
+
+# 显示结果摘要
+show_summary() {
+    show_step "性能分析结果摘要"
+    echo "1. cProfile 输出: $CPROFILE_OUTPUT (可用于 pstats 分析)"
+    echo "2. py-spy 火焰图: $FLAMEGRAPH_OUTPUT (可在浏览器中打开查看)"
+    echo "3. memory_profiler 输出: $MEMORY_PROFILE_OUTPUT (内存使用情况)"
+    echo "4. psutil 输出: $PSUTIL_OUTPUT (硬件资源使用情况)"
+    log_success "性能分析工具链执行完毕!"
+}
+# 整合所有分析结果
+integrate_all_results(){
+  show_step "步骤5 整合所有分析结果"
+
+  # 检查python脚本是否存在
+
+  if [ ! -f "$INTEGRATED_SCRIPT" ]; then
+     log_warning "整合脚本 $INTEGRATED_SCRIPT 不存在"
+     return 1
+  else
+    echo "结果整合中..."
+     # 构建命令参数
+    CMD="python $INTEGRATED_SCRIPT"
+
+    if [ -f "$CPROFILE_OUTPUT" ]; then
+        CMD="$CMD --cprofile $CPROFILE_OUTPUT"
+    fi
+
+    if [ -f "$MEMORY_PROFILE_OUTPUT" ]; then
+        CMD="$CMD --memory $MEMORY_PROFILE_OUTPUT"
+    fi
+
+    if [ -f "$FLAMEGRAPH_OUTPUT" ]; then
+        CMD="$CMD --flamegraph $FLAMEGRAPH_OUTPUT"
+    fi
+
+    if [ -f "$PSUTIL_OUTPUT" ]; then
+        CMD="$CMD --psutil $PSUTIL_OUTPUT"
+    fi
+
+    CMD="$CMD --output $INTEGRATED_REPORT"
+     # 执行整合脚本
+    log_info "执行整合命令: $CMD"
+    if eval "$CMD"; then
+        log_success "所有分析结果已整合至 $INTEGRATED_REPORT"
+        return 0
+    else
+        log_error "整合过程出错"
+        # 检查pandas是否存在
+        if ! python -c "import pandas" &> /dev/null; then
+           log_warning "未找到pandas,尝试安装..."
+           if pip3 install pandas -i https://pypi.tuna.tsinghua.edu.cn/simple; then
+              log_success "pandas 安装成功"
+           else
+              log_error "pandas 安装失败"
+              return 1
+           fi
+           # 尝试再次执行命令
+           if eval "$CMD"; then
+              log_success "所有分析结果已整合至 $INTEGRATED_REPORT"
+              return 0
+           fi
+        fi
+        return 1
+    fi
+  fi
+}
+
+
+
+# 主函数
+main() {
+    # 显示标题
+    show_header
+    # 检查脚本是否存在
+    if ! check_script_exists; then
+       log_error "请检查测试脚本是否存在."
+       exit 1
+    fi
+    # 创建结果保存目录
+    mk_dir
+    # 执行各项分析
+    run_cprofile  # cProfile 算法性能分析,统计主线程的函数调用次数和运行时间
+    run_py_spy  # py-spy 火焰图
+    run_memory_profiler  # 内存使用情况分析
+    run_psutil  # 使用psutil监控进程资源使用情况
+    show_summary  # 显示结果摘要
+    integrate_all_results  # 整合所有结果
+    # 自动打开结果文件
+    open_svg_file
+    open_prof_file
+}
+
+# 执行主函数
+main "$@"

+ 85 - 0
monitor_mnger.py

@@ -0,0 +1,85 @@
+import threading
+import time
+import psutil
+from monitor_util import Monitor
+
+class MonitorManager:
+    """监控管理器,负责管理多个进程的监控任务"""
+    def __init__(self):
+        self.monitor_threads = {}  # 存放监视线程
+        self.monitoring_data = {}
+        self.monitor_lock = threading.Lock()
+
+    def start_monitoring(self, pid:int, interval:int=2):
+        """开始监控指定PID的进程"""
+        try:
+            # 检查进程是否存在
+            if not psutil.pid_exists(pid):
+                return {"status": "error", "message": f"PID {pid} 的进程不存在"}
+
+            with self.monitor_lock:
+                # 检查是否已经监测该进程
+                if str(pid) in self.monitoring_data and self.monitoring_data[str(pid)]['is_running']:
+                    return {"status": "error", "message": f"PID {pid} 已经在监控中"}
+
+                self.monitoring_data[str(pid)] = {  # 构造监视器铭牌
+                    "pid": pid,
+                    "is_running": True  # 记录监视线程是否正在运行
+                }
+
+                # 启动监控线程
+                thread = threading.Thread(target=self._monitor_worker, args=(pid, interval))
+                thread.daemon = True  # 设置为守护线程
+                thread.start()
+                self.monitor_threads[str(pid)] = thread
+                return {"status": "success", "message": f"开始监控PID {pid}"}
+
+        except Exception as e:
+            return {"status": "error", "message": f"启动监控失败: {str(e)}"}
+
+    def stop_monitoring(self, pid:int):
+        """停止线程监测"""
+        with self.monitor_lock:
+            if str(pid) not in self.monitoring_data:
+                return {"status": "error", "message": f"尚未监测该进程:{pid}"}
+
+            elif str(pid) in self.monitoring_data and self.monitoring_data[str(pid)]['is_running']:# 如果正在监测该线程
+                self.monitoring_data[pid]["is_running"] = False
+                if str(pid) in self.monitor_threads:
+                    del self.monitor_threads[str(pid)]
+                return {"status": "success", "message": f"已停止监控PID {pid}"}
+            else:
+                return {"status": "error", "message": f"PID {pid} 未在监控中"}
+
+    def _monitor_worker(self, pid:int, interval:int):
+        """监控工作线程"""
+        # 在子线程中创建监视器实例,往后只有子线程自己使用这个监视器,没有静态条件
+        monitor = Monitor(pid)
+        try:
+            if monitor.process :
+                while True:
+                    with self.monitor_lock:
+                        flag = (self.monitoring_data[str(pid)]["is_running"]) and psutil.pid_exists(pid)
+                    if flag: # 如果需要运行监视且被监视进程存在
+                        # 更新监控数据
+                        monitor.update()
+                        # 存储数据点
+                        pass
+                        time.sleep(interval)
+                    else:
+                        # 如果停止监视,那么该子线程会被销毁
+                        break
+            else:
+                print(f'进程{pid}监视器创建失败')
+
+        except Exception as e:
+            print(f"监控PID {pid} 时发生错误: {str(e)}")
+        finally:
+            # 清理资源
+            with self.monitor_lock:
+                if str(pid) in self.monitoring_data:
+                    self.monitoring_data[pid]["is_running"] = False
+
+
+# 创建监控管理器实例
+monitor_manager = MonitorManager()

+ 54 - 0
monitor_online.py

@@ -0,0 +1,54 @@
+import sys
+import os
+sys.path.append(os.path.basename(__file__))
+from monitor_util import Monitor
+import psutil
+from datetime import datetime
+import subprocess
+from flask import Flask, render_template, request, jsonify
+from monitor_mnger import monitor_manager
+
+
+# 全局变量存储监控实例和监控状态
+app = Flask(__name__)
+
+@app.route('/monitor', methods=['GET', 'POST'])
+def monitor_control():
+    """监控控制接口"""
+    if request.method == 'GET':
+        # 返回监控界面
+        return render_template('monitor.html')
+    elif request.method == 'POST':
+        # 启动或停止监控
+        data = request.get_json()
+        if not data:
+            return jsonify({"status": "error", "message": "无效的请求数据"})
+
+        action = data.get('action')  # 获取行为
+        pid = data.get('pid')  # 获取进程id
+
+        # 参数检查
+        if not pid:
+            return jsonify({"status": "error", "message": "未提供PID参数"})
+        try:
+            pid = int(pid)
+        except ValueError:
+            return jsonify({"status": "error", "message": "PID必须是数字"})
+
+        # 开启或停止监控
+        if action == 'start':
+            # 启动监控
+            interval = data.get('interval', 2)
+            result = monitor_manager.start_monitoring(pid, interval)
+            return jsonify(result)
+
+        elif action == 'stop':
+            # 停止监控
+            result = monitor_manager.stop_monitoring(pid)
+            return jsonify(result)
+        else:
+            return jsonify({"status": "error", "message": "不支持的操作"})
+
+
+if __name__ == "__main__":
+    app.run(debug=True, host='0.0.0.0', port=5000)

+ 158 - 0
monitor_util.py

@@ -0,0 +1,158 @@
+import psutil
+import time
+from datetime import datetime
+import os
+import json
+import csv
+
+class Monitor:
+    def __init__(self, pid:int, alias:str=''):
+        self.pid = pid
+        self.process = None
+        self.curr_disk_io_counter = None  # 磁盘读写计数器
+        self.curr_system_net_io_counter = psutil.net_io_counters()  # 系统网络读写计数器
+        self.data_points=[] # 数据点
+        self.max_count = 1
+        self.usage = {
+            "pid":'',            # 进程名称
+            "now_time":'',       # 当前时间
+            "cpu_pct": '',       # cpu使用率
+            "rss":'',            # 物理内存
+            "vms":'',            # 虚拟内存
+            "mem_pct":'',        # 内存使用率
+            "disk_read": '',     # 磁盘读速率
+            "disk_write": '',    # 磁盘写速率
+            "sys_net_recv": '',  # 系统网络下载速率
+            "sys_net_send": '',  # 系统网络上传速率
+            "name": '',          # 进程名称
+            "status": '',        # 进程状态
+            "pwd":'',            # 当前工作目录
+            "exe":'',            # 可执行文件路径
+            "start_time": '',    # 进程启动时间
+        }
+        self.usage_map = {
+            "pid": '进程名称',
+            "now_time": '当前时间',
+            "cpu_pct": 'cpu使用率',
+            "rss": '物理内存',
+            "vms": '虚拟内存',
+            "mem_pct": '内存使用率',
+            "disk_read": '磁盘读速率',
+            "disk_write": '磁盘写速率',
+            "sys_net_recv": '系统网络下载速率',
+            "sys_net_send": '系统网络上传速率',
+            "name": '进程名称',
+            "status": '进程状态',
+            "pwd": '当前工作目录',
+            "exe": '可执行文件路径',
+            "start_time": '进程启动时间',
+        }
+
+        try:
+            self.process = psutil.Process(pid)
+            self.curr_disk_io_counter = self.process.io_counters()
+
+            print(f"成功附加到进程: {self.process.name()} (PID: {pid})")
+            self.usage["name"] = self.process.name()
+            self.usage["pid"] = f'{self.process.pid}'
+            self.usage["pwd"] = self.process.cwd()
+            self.usage["exe"] = self.process.exe()
+            self.usage["start_time"] = datetime.fromtimestamp(self.process.create_time()).strftime('%Y-%m-%d %H:%M:%S')
+        except psutil.NoSuchProcess:
+            print(f"未找到PID为 {pid} 的进程。")
+            self.process = None
+
+    def get_memory_usage_info(self):
+        """内存使用信息"""
+        if not self.process:
+            raise RuntimeError(f'监控程序未能找到进程:{self.pid}')
+        mem_info = self.process.memory_info()
+        rss_mb = mem_info.rss / (1024 * 1024)  # 转换为MB  物理内存
+        vms_mb = mem_info.vms / (1024 * 1024)  # 虚拟内存
+        memory_usage_percent = self.process.memory_percent()
+        self.usage["rss"] = f'{rss_mb:.2f}MB'  # 物理内存
+        self.usage["vms"] = f'{vms_mb:.2f}MB'  # 虚拟内存
+        self.usage["mem_pct"] = f'{memory_usage_percent:.2f}%'  # 占用百分比
+
+    def get_cpu_usage_info(self):
+        # 获取CPU使用率,设置采样间隔为1秒
+        cpu_usage = self.process.cpu_percent(interval=1.0)
+        self.usage["cpu_pct"] = f'{cpu_usage:.2f}%'
+
+    def get_disk_io_info(self):
+        """统计磁盘读写速度"""
+        new_io_counter = self.process.io_counters()
+        read_bytes_diff = (new_io_counter.read_bytes - self.curr_disk_io_counter.read_bytes) / (1024 ** 2)
+        write_bytes_diff = (new_io_counter.write_bytes - self.curr_disk_io_counter.write_bytes) / (1024 ** 2)
+        if not self.usage.get('now_time', None):
+            raise RuntimeError('存在逻辑错误, 时间获取前被使用')
+        time_diff = (datetime.now()-datetime.strptime(self.usage['now_time'], '%Y-%m-%d %H:%M:%S')).total_seconds()
+        # 计算速率MB/秒
+        read_speed_mB = (read_bytes_diff / time_diff) if time_diff > 0 else 0
+        write_speed_mB = (write_bytes_diff / time_diff) if time_diff > 0 else 0
+        self.usage['disk_read'] = f'{read_speed_mB:.2f} MB/s'
+        self.usage['disk_write'] = f'{write_speed_mB:.2f} MB/s'
+        self.curr_disk_io_counter = new_io_counter
+
+    def get_net_io_info(self):
+        """统计网络上下行速度"""
+        new_net_io_counter = psutil.net_io_counters()
+        sent_bytes_mB = (new_net_io_counter.bytes_sent - self.curr_system_net_io_counter.bytes_sent) / (1024 ** 2)
+        recv_bytes_mB = (new_net_io_counter.bytes_recv - self.curr_system_net_io_counter.bytes_recv) / (1024 ** 2)
+        if not self.usage.get('now_time', None):
+            raise RuntimeError('存在逻辑错误, 时间获取前被使用')
+        time_diff = (datetime.now()-datetime.strptime(self.usage['now_time'], '%Y-%m-%d %H:%M:%S')).total_seconds()
+        sys_net_send_speed = (sent_bytes_mB / time_diff ) if time_diff > 0 else 0
+        sys_net_recv_speed = (recv_bytes_mB / time_diff ) if time_diff > 0 else 0
+        self.usage['sys_net_send'] = f'{sys_net_send_speed:.2f} MB/s'
+        self.usage['sys_net_recv'] = f'{sys_net_recv_speed:.2f} MB/s'
+        self.curr_system_net_io_counter = new_net_io_counter
+
+
+    def update(self, output_file=None):
+        self.usage['now_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
+        self.usage['status'] = self.process.status()
+        # 刷新内存使用情况
+        self.get_memory_usage_info()
+        # 刷新cpu使用情况
+        self.get_cpu_usage_info()
+        # 刷新硬盘读取情况
+        self.get_disk_io_info()
+        # 刷新网络上下行情况
+        self.get_net_io_info()
+        if output_file:
+            self.data_points.append(self.usage.copy())
+            if len(self.data_points) >= self.max_count:  # 如果达到100个数据点,则保存到CSV文件中,并清空数据点
+                # 检查文件是否存在,以决定是否需要写入标题行
+                file_exists = os.path.isfile(output_file)
+                with open(output_file, 'a', newline='', encoding='utf-8') as csvfile:
+                    writer = csv.DictWriter(csvfile, fieldnames=self.usage.keys())
+                    # 如果文件不存在,写入标题行
+                    print(f'psutil 保存文件:{output_file}')
+                    if not file_exists:
+                        writer.writeheader()
+                    # 写入数据行
+                    writer.writerows(self.data_points)
+                # 清空数据点列表
+                self.data_points = []
+
+    def start(self, interval=1, output_file=None):
+        if self.process:
+            while psutil.pid_exists(self.pid):
+                try:
+                    with self.process.oneshot():
+                        self.update(output_file=output_file)
+                        print(self.usage)
+                        time.sleep(interval)
+                except Exception as e:
+                    break
+
+
+if __name__ == "__main__":
+    import argparse
+    parser = argparse.ArgumentParser(description='Py进程监视器')
+    parser.add_argument('--pid', '-p', type=int, required=True , help='请输入需要监控的进程id')
+    parser.add_argument('--output', '-o', type=str, required=True , help='请输入需要监控的进程id')
+    args = parser.parse_args()
+    m = Monitor(args.pid)
+    m.start(output_file=args.output)

+ 397 - 0
plot.py

@@ -0,0 +1,397 @@
+import json
+import argparse
+import matplotlib.pyplot as plt
+import numpy as np
+from datetime import datetime
+from matplotlib.font_manager import FontProperties
+
+# 设置中文字体支持
+plt.rcParams['font.sans-serif'] = ['SimHei', 'FangSong', 'Arial Unicode MS']
+plt.rcParams['axes.unicode_minus'] = False
+
+def read_json(file_path):
+    with open(file_path, 'r', encoding='utf-8') as f:
+        data = json.load(f)
+    return data
+
+def plot_cprofile_table(ax, cprofile_data):
+    """绘制cProfile详细信息表格"""
+    if not cprofile_data or 'points' not in cprofile_data:
+        ax.text(0.5, 0.5, '无cProfile数据', ha='center', va='center', transform=ax.transAxes)
+        ax.set_title('函数运行详细信息')
+        return
+    
+    # 只取前15个最耗时的函数
+    fun_num = 15
+    points = cprofile_data['points'][:fun_num]
+    
+    # 准备表格数据
+    table_data = []
+    for point in points:
+        # 简化函数名显示
+        func_name = point['function'][1:-1]
+        func_name = func_name.split(',')[-1].strip()
+        func_name = func_name[1:-1]
+
+        # 限制函数名长度,但保留足够空间显示完整信息
+        func_name_display = func_name[:35] + '...' if len(func_name) > 35 else func_name
+        # 将数据点添加到表格
+        table_data.append([
+            func_name_display,
+            point['call_count'],
+            f"{point['total_time']:.6f}",
+            f"{point['cumulative_time']:.6f}"
+        ])
+    
+    # 创建表格
+    columns = ['函数名称', '调用次数', '总时间(s)', '累计时间(s)']
+    table = ax.table(cellText=table_data, colLabels=columns, cellLoc='center', loc='center')
+    table.auto_set_font_size(False)
+    table.set_fontsize(9)
+    table.scale(1, 1.5)
+    
+    # 设置表格样式
+    for i in range(len(columns)):
+        table[(0, i)].set_facecolor('#4CAF50')
+        table[(0, i)].set_text_props(weight='bold', color='white')
+    # 根据函数数量动态调整标题距离
+    # 每个函数行大约需要8个单位的高度,加上基础padding
+    pad_value = 8 + len(points) * 3
+    ax.set_title(f'函数运行详细信息 (Top {fun_num} 函数)', fontsize=14, pad=pad_value)
+    # 坐标轴掩藏
+    ax.set_xticks([])
+    ax.set_yticks([])
+    ax.spines['top'].set_visible(False)
+    ax.spines['right'].set_visible(False)
+    ax.spines['bottom'].set_visible(False)
+    ax.spines['left'].set_visible(False)
+
+
+def plot_cprofile_bar_chart(ax, cprofile_data):
+    """绘制cProfile总时间柱状图"""
+    if not cprofile_data or 'points' not in cprofile_data:
+        ax.text(0.5, 0.5, '无cProfile数据', ha='center', va='center', transform=ax.transAxes)
+        ax.set_title('函数运行总时间')
+        return
+    
+    # 只取前N个最耗时的函数
+    fun_num = 15
+    points = cprofile_data['points'][:fun_num]
+    
+    # 提取函数名和总时间
+    functions = []
+    total_times = []
+    
+    for point in points:
+        # 简化函数名显示
+        func_name = point['function'][1:-1]
+        func_name = func_name.split(',')[-1].strip()
+        func_name = func_name[1:-1]
+        
+        # 限制函数名长度
+        func_name_display = func_name[:35] + '...' if len(func_name) > 35 else func_name
+        functions.append(func_name_display)
+        total_times.append(point['total_time'])
+    
+    # 创建垂直柱状图,使用渐变色彩
+    x_pos = np.arange(len(functions))
+    colors = plt.cm.viridis(np.linspace(0, 1, len(functions)))
+    bars = ax.bar(x_pos, total_times, color=colors)
+    
+    # 设置坐标轴
+    ax.set_xticks(x_pos)
+    ax.set_xticklabels(functions, rotation=30, ha='right', fontsize=9)
+    ax.set_ylabel('总时间 (秒)', fontsize=12)
+    ax.set_title(f'函数运行总时间 (Top {fun_num} 函数)', fontsize=14, pad=20)
+    
+    # 改善网格线样式
+    ax.grid(axis='y', alpha=0.7, linestyle='--', linewidth=0.5)
+    ax.set_axisbelow(True)
+    
+    # 在柱状图上添加数值标签,优化显示效果
+    for bar, time in zip(bars, total_times):
+        height = bar.get_height()
+        ax.text(bar.get_x() + bar.get_width()/2., height,
+                f'{time:.6f}', ha='center', va='bottom', fontsize=8, 
+                rotation=0, weight='bold')
+    
+    # 添加边框
+    for spine in ax.spines.values():
+        spine.set_linewidth(0.5)
+
+def plot_memory_data(ax, memory_data):
+    """绘制内存使用数据"""
+    if not memory_data or 'points' not in memory_data:
+        ax.text(0.5, 0.5, '无内存数据', ha='center', va='center', transform=ax.transAxes)
+        ax.set_title('memory_profiler 内存使用情况')
+        return
+    
+    timestamps = [point['timestamp'] for point in memory_data['points']]
+    memory_values = [point['memory'] for point in memory_data['points']]
+    
+    # 转换时间戳为相对时间(秒)
+    start_time = timestamps[0] if timestamps else 0
+    relative_times = [t - start_time for t in timestamps]
+    
+    # 查找内存峰值及其位置
+    max_memory = max(memory_values) if memory_values else 0
+    max_index = memory_values.index(max_memory) if memory_values else 0
+    max_time = relative_times[max_index] if relative_times else 0
+    
+    # 绘制内存使用情况曲线
+    line, = ax.plot(relative_times, memory_values, marker='o', markersize=3, linewidth=1.5)
+    
+    # 在峰值点添加特殊标记
+    ax.plot(max_time, max_memory, marker='o', markersize=8, color='red',
+                          markerfacecolor='none', markeredgewidth=2, label=f'峰值: {max_memory:.2f} MB')
+    
+    ax.set_xlabel('时间 (秒)')
+    ax.set_ylabel('内存使用量 (MB)')
+    ax.set_title(f'进程内存使用情况 (峰值: {max_memory:.2f} MB at {max_time:.1f}s)')
+    ax.grid(True, alpha=0.3)
+    ax.legend()
+
+def plot_psutil_data(ax, psutil_data):
+    """绘制psutil系统资源数据"""
+    if not psutil_data or 'points' not in psutil_data:
+        ax.text(0.5, 0.5, '无进程资源数据', ha='center', va='center', transform=ax.transAxes)
+        ax.set_title('进程资源使用情况')
+        return
+    
+    points = psutil_data['points']
+    if not points:
+        ax.text(0.5, 0.5, '无进程资源数据', ha='center', va='center', transform=ax.transAxes)
+        ax.set_title('进程资源使用情况')
+        return
+    
+    # 提取数据并转换时间字符串为时间戳
+    timestamps = []
+    rss_values = []
+    vms_values = []
+    cpu_values = []
+    mem_pct_values = []
+    
+    for point in points:
+        # 解析时间字符串并转换为时间戳
+        try:
+            dt = datetime.strptime(point['now_time'], '%Y-%m-%d %H:%M:%S')
+            timestamps.append(dt.timestamp())
+        except ValueError:
+            # 如果解析失败,使用索引作为后备
+            timestamps.append(len(timestamps))
+            
+    # 转换时间戳为相对时间(秒)
+    start_time = timestamps[0] if timestamps else 0
+    relative_times = [t - start_time for t in timestamps]
+    
+    for point in points:
+        # 解析RSS内存值
+        rss_str = point['rss'].replace('MB', '')
+        try:
+            rss_values.append(float(rss_str))
+        except ValueError:
+            rss_values.append(0)
+            
+        # 解析VMS内存值
+        vms_str = point['vms'].replace('MB', '')
+        try:
+            vms_values.append(float(vms_str))
+        except ValueError:
+            vms_values.append(0)
+        
+        # 解析CPU百分比
+        cpu_str = point['cpu_pct'].replace('%', '')
+        try:
+            cpu_values.append(float(cpu_str))
+        except ValueError:
+            cpu_values.append(0)
+            
+        # 解析内存占用率
+        mem_pct_str = point['mem_pct'].replace('%', '')
+        try:
+            mem_pct_values.append(float(mem_pct_str))
+        except ValueError:
+            mem_pct_values.append(0)
+    
+    # 绘制双轴图
+    ax2 = ax.twinx()
+    
+    # 物理内存使用量(蓝色)
+    line1, = ax.plot(relative_times, rss_values, marker='o', color='blue', label='物理内存(RSS)')
+    # 虚拟内存使用量(绿色)
+    line3, = ax.plot(relative_times, vms_values, marker='^', color='green', label='虚拟内存(VMS)')
+    ax.set_xlabel('时间 (秒)')
+    ax.set_ylabel('内存使用量 (MB)', color='blue')
+    ax.tick_params(axis='y', labelcolor='blue')
+    
+    # CPU使用率(红色)和内存占用率(紫色)
+    line2, = ax2.plot(relative_times, cpu_values, marker='s', color='red', label='CPU使用率')
+    line4, = ax2.plot(relative_times, mem_pct_values, marker='d', color='purple', label='内存占用率')
+    ax2.set_ylabel('百分比 (%)', color='red')
+    ax2.tick_params(axis='y', labelcolor='red')
+    
+    # 合并图例
+    lines = [line1, line3, line2, line4]
+    labels = [l.get_label() for l in lines]
+    ax.legend(lines, labels, loc='upper left')
+    
+    ax.set_title('进程资源使用情况')
+    ax.grid(True, alpha=0.3)
+
+def plot_network_data(ax, psutil_data):
+    """绘制网络使用数据"""
+    if not psutil_data or 'points' not in psutil_data:
+        ax.text(0.5, 0.5, '无网络数据', ha='center', va='center', transform=ax.transAxes)
+        ax.set_title('系统网络使用情况')
+        return
+    
+    points = psutil_data['points']
+    if not points:
+        ax.text(0.5, 0.5, '无网络数据', ha='center', va='center', transform=ax.transAxes)
+        ax.set_title('系统网络使用情况')
+        return
+    
+    # 提取数据并转换时间字符串为时间戳
+    from datetime import datetime
+    timestamps = []
+    net_recv_values = []
+    net_send_values = []
+    
+    for point in points:
+        # 解析时间字符串并转换为时间戳
+        try:
+            dt = datetime.strptime(point['now_time'], '%Y-%m-%d %H:%M:%S')
+            timestamps.append(dt.timestamp())
+        except ValueError:
+            # 如果解析失败,使用索引作为后备
+            timestamps.append(len(timestamps))
+    
+    # 转换为相对时间(秒)
+    start_time = timestamps[0] if timestamps else 0
+    relative_times = [t - start_time for t in timestamps]
+    
+    for point in points:
+        # 解析网络接收值
+        net_recv_str = point['sys_net_recv'].replace('MB/s', '').replace('MB', '').replace(' ', '')
+        try:
+            net_recv_values.append(float(net_recv_str))
+        except ValueError:
+            net_recv_values.append(0)
+            
+        # 解析网络发送值
+        net_send_str = point['sys_net_send'].replace('MB/s', '').replace('MB', '').replace(' ', '')
+        try:
+            net_send_values.append(float(net_send_str))
+        except ValueError:
+            net_send_values.append(0)
+    
+    # 绘制网络使用情况
+    ax.plot(relative_times, net_recv_values, marker='o', color='blue', label='网络接收')
+    ax.plot(relative_times, net_send_values, marker='s', color='red', label='网络发送')
+    
+    ax.set_xlabel('时间 (秒)')
+    ax.set_ylabel('速率 (MB/s)')
+    ax.set_title('系统网络使用情况')
+    ax.grid(True, alpha=0.3)
+    ax.legend()
+
+def plot_disk_io_data(ax, psutil_data):
+    """绘制进程IO数据"""
+    if not psutil_data or 'points' not in psutil_data:
+        ax.text(0.5, 0.5, '无进程IO数据', ha='center', va='center', transform=ax.transAxes)
+        ax.set_title('进程IO情况')
+        return
+    
+    points = psutil_data['points']
+    if not points:
+        ax.text(0.5, 0.5, '无进程IO数据', ha='center', va='center', transform=ax.transAxes)
+        ax.set_title('进程IO情况')
+        return
+    
+    # 提取数据并转换时间字符串为时间戳
+    timestamps = []
+    disk_read_values = []
+    disk_write_values = []
+    
+    for point in points:
+        # 解析时间字符串并转换为时间戳
+        try:
+            dt = datetime.strptime(point['now_time'], '%Y-%m-%d %H:%M:%S')
+            timestamps.append(dt.timestamp())
+        except ValueError:
+            # 如果解析失败,使用索引作为后备
+            timestamps.append(len(timestamps))
+    
+    # 转换为相对时间(秒)
+    start_time = timestamps[0] if timestamps else 0
+    relative_times = [t - start_time for t in timestamps]
+    
+    for point in points:
+        # 解析磁盘读取值
+        disk_read_str = point['disk_read'].replace('MB/s', '').replace('MB', '').replace(' ', '')
+        try:
+            disk_read_values.append(float(disk_read_str))
+        except ValueError:
+            disk_read_values.append(0)
+            
+        # 解析磁盘写入值
+        disk_write_str = point['disk_write'].replace('MB/s', '').replace('MB', '').replace(' ', '')
+        try:
+            disk_write_values.append(float(disk_write_str))
+        except ValueError:
+            disk_write_values.append(0)
+    
+    # 绘制磁盘IO情况
+    ax.plot(relative_times, disk_read_values, marker='o', color='blue', label='磁盘读取')
+    ax.plot(relative_times, disk_write_values, marker='s', color='red', label='磁盘写入')
+    
+    ax.set_xlabel('时间 (秒)')
+    ax.set_ylabel('速率 (MB/s)')
+    ax.set_title('进程IO情况')
+    ax.grid(True, alpha=0.3)
+    ax.legend()
+
+def main():
+    parser = argparse.ArgumentParser(description='绘制性能分析结果图')
+    parser.add_argument('--input','-i', default='./results/performance_analysis_report.json')
+    parser.add_argument('--output', '-o', default='./results/performance_analysis_report.png')
+    args = parser.parse_args()
+
+    # 读取json数据
+    data = read_json(args.input)
+    
+    # 创建更大的图表
+    fig = plt.figure(figsize=(20, 18))
+    fig.suptitle('Python 性能分析报告', fontsize=20, fontweight='bold')
+    
+    # 创建子图
+    # cProfile 表格
+    ax1 = plt.subplot2grid((4, 2), (0, 0), colspan=1)
+    # cProfile 柱状图
+    ax2 = plt.subplot2grid((4, 2), (0, 1), colspan=1)
+    # 内存使用情况
+    ax3 = plt.subplot2grid((4, 2), (1, 0), colspan=1)
+    # 系统资源监控
+    ax4 = plt.subplot2grid((4, 2), (1, 1), colspan=1)
+    # 网络使用情况
+    ax5 = plt.subplot2grid((4, 2), (2, 0), colspan=1)
+    # 磁盘读写情况
+    ax6 = plt.subplot2grid((4, 2), (2, 1), colspan=1)
+    
+    # 绘制各个子图
+    plot_cprofile_table(ax1, data.get('analysis_results', {}).get('cprofile', {}))
+    plot_cprofile_bar_chart(ax2, data.get('analysis_results', {}).get('cprofile', {}))
+    plot_memory_data(ax3, data.get('analysis_results', {}).get('memory_profile', {}))
+    plot_psutil_data(ax4, data.get('analysis_results', {}).get('psutil', {}))
+    plot_network_data(ax5, data.get('analysis_results', {}).get('psutil', {}))
+    plot_disk_io_data(ax6, data.get('analysis_results', {}).get('psutil', {}))
+    
+    # 调整布局
+    plt.tight_layout()
+    
+    # 保存图像
+    plt.savefig(args.output, dpi=300, bbox_inches='tight')
+    print(f"性能分析图表已保存至: {args.output}")
+
+if __name__ == '__main__':
+    main()

BIN
results/cprofile_output.prof


BIN
results/mprofile_memory_plot.png


+ 95 - 0
results/mprofile_output.dat

@@ -0,0 +1,95 @@
+CMDLINE /home/jiyuhang/miniconda3/envs/testpy1/bin/python3.12 ./test/test_script.py
+MEM 7.500000 1765796405.9547
+MEM 22.343750 1765796406.0553
+MEM 22.343750 1765796406.1556
+MEM 22.343750 1765796406.2561
+MEM 22.343750 1765796406.3565
+MEM 22.343750 1765796406.4569
+MEM 22.343750 1765796406.5572
+MEM 22.343750 1765796406.6576
+MEM 22.343750 1765796406.7579
+MEM 22.343750 1765796406.8583
+MEM 22.343750 1765796406.9587
+MEM 22.343750 1765796407.0591
+MEM 22.343750 1765796407.1595
+MEM 22.343750 1765796407.2598
+MEM 22.343750 1765796407.3602
+MEM 22.343750 1765796407.4605
+MEM 22.343750 1765796407.5611
+MEM 22.343750 1765796407.6618
+MEM 22.343750 1765796407.7622
+MEM 22.343750 1765796407.8626
+MEM 22.343750 1765796407.9630
+MEM 22.343750 1765796408.0634
+MEM 22.343750 1765796408.1638
+MEM 22.343750 1765796408.2641
+MEM 22.343750 1765796408.3645
+MEM 22.343750 1765796408.4648
+MEM 22.343750 1765796408.5650
+MEM 22.343750 1765796408.6652
+MEM 22.343750 1765796408.7657
+MEM 22.343750 1765796408.8659
+MEM 22.343750 1765796408.9663
+MEM 22.500000 1765796409.0665
+MEM 22.500000 1765796409.1669
+MEM 22.500000 1765796409.2672
+MEM 22.500000 1765796409.3675
+MEM 22.500000 1765796409.4679
+MEM 22.500000 1765796409.5682
+MEM 22.500000 1765796409.6686
+MEM 22.500000 1765796409.7689
+MEM 22.500000 1765796409.8692
+MEM 22.500000 1765796409.9696
+MEM 22.500000 1765796410.0698
+MEM 22.500000 1765796410.1703
+MEM 22.500000 1765796410.2707
+MEM 22.500000 1765796410.3709
+MEM 22.500000 1765796410.4712
+MEM 22.500000 1765796410.5715
+MEM 22.500000 1765796410.6718
+MEM 22.500000 1765796410.7721
+MEM 22.500000 1765796410.8724
+MEM 22.500000 1765796410.9728
+MEM 22.500000 1765796411.0746
+MEM 22.500000 1765796411.1749
+MEM 22.500000 1765796411.2752
+MEM 22.500000 1765796411.3754
+MEM 22.500000 1765796411.4758
+MEM 22.500000 1765796411.5742
+MEM 22.500000 1765796411.6745
+MEM 22.500000 1765796411.7748
+MEM 22.500000 1765796411.8751
+MEM 22.500000 1765796411.9754
+MEM 22.500000 1765796412.0758
+MEM 22.500000 1765796412.1762
+MEM 22.500000 1765796412.2764
+MEM 22.500000 1765796412.3768
+MEM 22.500000 1765796412.4772
+MEM 22.500000 1765796412.5774
+MEM 22.500000 1765796412.6778
+MEM 22.500000 1765796412.7780
+MEM 22.500000 1765796412.8784
+MEM 22.500000 1765796412.9788
+MEM 22.500000 1765796413.0791
+MEM 34.375000 1765796413.1794
+MEM 88.125000 1765796413.2798
+MEM 24.722656 1765796413.3800
+MEM 24.722656 1765796413.4803
+MEM 24.722656 1765796413.5806
+MEM 24.722656 1765796413.6809
+MEM 24.722656 1765796413.7812
+MEM 24.722656 1765796413.8815
+MEM 24.722656 1765796413.9819
+MEM 24.722656 1765796414.0822
+MEM 24.722656 1765796414.1826
+MEM 24.722656 1765796414.2830
+MEM 24.722656 1765796414.3834
+MEM 24.722656 1765796414.4838
+MEM 24.722656 1765796414.5841
+MEM 24.722656 1765796414.6844
+MEM 24.722656 1765796414.7847
+MEM 24.722656 1765796414.8852
+MEM 24.722656 1765796414.9856
+MEM 24.722656 1765796415.0859
+MEM 24.722656 1765796415.1863
+MEM 24.722656 1765796415.2867

+ 573 - 0
results/performance_analysis_report.json

@@ -0,0 +1,573 @@
+{
+  "timestamp": "2025-12-15T19:00:29.845166",
+  "analysis_results": {
+    "cprofile": {
+      "type": "cprofile",
+      "points": [
+        {
+          "function": "('~', 0, '<built-in method builtins.exec>')",
+          "call_count": 1,
+          "total_time": 6.289e-06,
+          "cumulative_time": 9.569391957
+        },
+        {
+          "function": "('./test/test_script.py', 1, '<module>')",
+          "call_count": 1,
+          "total_time": 7.466e-06,
+          "cumulative_time": 9.569385668
+        },
+        {
+          "function": "('./test/test_script.py', 28, 'main')",
+          "call_count": 1,
+          "total_time": 0.012500885000000002,
+          "cumulative_time": 9.562481916000001
+        },
+        {
+          "function": "('~', 0, '<built-in method time.sleep>')",
+          "call_count": 5,
+          "total_time": 9.127744553000001,
+          "cumulative_time": 9.127744553000001
+        },
+        {
+          "function": "('./test/test_script.py', 9, 'cpu_intensive_task')",
+          "call_count": 1,
+          "total_time": 0.11295076000000001,
+          "cumulative_time": 0.231741562
+        },
+        {
+          "function": "('./test/test_script.py', 21, 'memory_intensive_task')",
+          "call_count": 1,
+          "total_time": 0.18289659200000002,
+          "cumulative_time": 0.19026621300000002
+        },
+        {
+          "function": "('./test/test_script.py', 16, 'io_simulation_task')",
+          "call_count": 1,
+          "total_time": 4.0370000000000005e-06,
+          "cumulative_time": 0.10028563300000001
+        },
+        {
+          "function": "('~', 0, '<built-in method math.sin>')",
+          "call_count": 1000000,
+          "total_time": 0.067158061,
+          "cumulative_time": 0.067158061
+        },
+        {
+          "function": "('~', 0, '<built-in method math.sqrt>')",
+          "call_count": 1000000,
+          "total_time": 0.051632741,
+          "cumulative_time": 0.051632741
+        },
+        {
+          "function": "('~', 0, \"<method 'append' of 'list' objects>\")",
+          "call_count": 100002,
+          "total_time": 0.007368922000000001,
+          "cumulative_time": 0.007368922000000001
+        },
+        {
+          "function": "('<frozen importlib._bootstrap>', 1349, '_find_and_load')",
+          "call_count": 1,
+          "total_time": 3.8218000000000006e-05,
+          "cumulative_time": 0.006896286000000001
+        },
+        {
+          "function": "('<frozen importlib._bootstrap>', 1304, '_find_and_load_unlocked')",
+          "call_count": 1,
+          "total_time": 5.9380000000000006e-06,
+          "cumulative_time": 0.006777475000000001
+        },
+        {
+          "function": "('<frozen importlib._bootstrap>', 1240, '_find_spec')",
+          "call_count": 1,
+          "total_time": 1.1858e-05,
+          "cumulative_time": 0.0064816380000000005
+        },
+        {
+          "function": "('<frozen importlib._bootstrap_external>', 1524, 'find_spec')",
+          "call_count": 1,
+          "total_time": 2.1620000000000002e-06,
+          "cumulative_time": 0.006444345000000001
+        },
+        {
+          "function": "('<frozen importlib._bootstrap_external>', 1495, '_get_spec')",
+          "call_count": 1,
+          "total_time": 1.0066e-05,
+          "cumulative_time": 0.006442183000000001
+        },
+        {
+          "function": "('<frozen importlib._bootstrap_external>', 1597, 'find_spec')",
+          "call_count": 4,
+          "total_time": 2.9501e-05,
+          "cumulative_time": 0.004336908
+        },
+        {
+          "function": "('<frozen importlib._bootstrap_external>', 140, '_path_stat')",
+          "call_count": 7,
+          "total_time": 4.175e-06,
+          "cumulative_time": 0.0033615090000000004
+        },
+        {
+          "function": "('~', 0, '<built-in method posix.stat>')",
+          "call_count": 7,
+          "total_time": 0.003357334,
+          "cumulative_time": 0.003357334
+        },
+        {
+          "function": "('<frozen importlib._bootstrap_external>', 1648, '_fill_cache')",
+          "call_count": 1,
+          "total_time": 6.159000000000001e-06,
+          "cumulative_time": 0.002959761
+        },
+        {
+          "function": "('~', 0, '<built-in method posix.listdir>')",
+          "call_count": 1,
+          "total_time": 0.002952239,
+          "cumulative_time": 0.002952239
+        }
+      ],
+      "num": 20
+    },
+    "memory_profile": {
+      "type": "memory_profile",
+      "points": [
+        {
+          "timestamp": 1765796405.9547,
+          "memory": 7.5
+        },
+        {
+          "timestamp": 1765796406.0553,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796406.1556,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796406.2561,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796406.3565,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796406.4569,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796406.5572,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796406.6576,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796406.7579,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796406.8583,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796406.9587,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796407.0591,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796407.1595,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796407.2598,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796407.3602,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796407.4605,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796407.5611,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796407.6618,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796407.7622,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796407.8626,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796407.963,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796408.0634,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796408.1638,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796408.2641,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796408.3645,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796408.4648,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796408.565,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796408.6652,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796408.7657,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796408.8659,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796408.9663,
+          "memory": 22.34375
+        },
+        {
+          "timestamp": 1765796409.0665,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796409.1669,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796409.2672,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796409.3675,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796409.4679,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796409.5682,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796409.6686,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796409.7689,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796409.8692,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796409.9696,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796410.0698,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796410.1703,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796410.2707,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796410.3709,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796410.4712,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796410.5715,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796410.6718,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796410.7721,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796410.8724,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796410.9728,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796411.0746,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796411.1749,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796411.2752,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796411.3754,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796411.4758,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796411.5742,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796411.6745,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796411.7748,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796411.8751,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796411.9754,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796412.0758,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796412.1762,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796412.2764,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796412.3768,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796412.4772,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796412.5774,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796412.6778,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796412.778,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796412.8784,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796412.9788,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796413.0791,
+          "memory": 22.5
+        },
+        {
+          "timestamp": 1765796413.1794,
+          "memory": 34.375
+        },
+        {
+          "timestamp": 1765796413.2798,
+          "memory": 88.125
+        },
+        {
+          "timestamp": 1765796413.38,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796413.4803,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796413.5806,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796413.6809,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796413.7812,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796413.8815,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796413.9819,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796414.0822,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796414.1826,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796414.283,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796414.3834,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796414.4838,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796414.5841,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796414.6844,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796414.7847,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796414.8852,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796414.9856,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796415.0859,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796415.1863,
+          "memory": 24.722656
+        },
+        {
+          "timestamp": 1765796415.2867,
+          "memory": 24.722656
+        }
+      ],
+      "num": 94,
+      "peak_memory": 88.125
+    },
+    "pyspy_flamegraph": {
+      "type": "pyspy_flamegraph",
+      "file_size_bytes": 24019,
+      "status": "generated"
+    },
+    "psutil": {
+      "type": "psutil",
+      "points": [
+        {
+          "pid": 126890,
+          "now_time": "2025-12-15 19:00:17",
+          "cpu_pct": "0.00%",
+          "rss": "8.59MB",
+          "vms": "15.98MB",
+          "mem_pct": "0.11%",
+          "disk_read": "0.00 MB/s",
+          "disk_write": "0.00 MB/s",
+          "sys_net_recv": "0.00 MB/s",
+          "sys_net_send": "0.00 MB/s"
+        },
+        {
+          "pid": 126890,
+          "now_time": "2025-12-15 19:00:19",
+          "cpu_pct": "0.00%",
+          "rss": "8.75MB",
+          "vms": "15.98MB",
+          "mem_pct": "0.11%",
+          "disk_read": "0.00 MB/s",
+          "disk_write": "0.00 MB/s",
+          "sys_net_recv": "0.00 MB/s",
+          "sys_net_send": "0.00 MB/s"
+        },
+        {
+          "pid": 126890,
+          "now_time": "2025-12-15 19:00:21",
+          "cpu_pct": "0.00%",
+          "rss": "8.75MB",
+          "vms": "15.98MB",
+          "mem_pct": "0.11%",
+          "disk_read": "0.00 MB/s",
+          "disk_write": "0.00 MB/s",
+          "sys_net_recv": "0.00 MB/s",
+          "sys_net_send": "0.00 MB/s"
+        },
+        {
+          "pid": 126890,
+          "now_time": "2025-12-15 19:00:24",
+          "cpu_pct": "0.00%",
+          "rss": "94.83MB",
+          "vms": "101.82MB",
+          "mem_pct": "1.21%",
+          "disk_read": "0.00 MB/s",
+          "disk_write": "0.00 MB/s",
+          "sys_net_recv": "0.00 MB/s",
+          "sys_net_send": "0.00 MB/s"
+        }
+      ],
+      "num": 4
+    }
+  }
+}

BIN
results/performance_analysis_report.png


+ 5 - 0
results/psutil_output.csv

@@ -0,0 +1,5 @@
+pid,now_time,cpu_pct,rss,vms,mem_pct,disk_read,disk_write,sys_net_recv,sys_net_send,name,status,pwd,exe,start_time
+126890,2025-12-15 19:00:17,0.00%,8.59MB,15.98MB,0.11%,0.00 MB/s,0.00 MB/s,0.00 MB/s,0.00 MB/s,python,sleeping,/mnt/d/code/listen_py,/home/jiyuhang/miniconda3/envs/testpy1/bin/python3.12,2025-12-15 19:00:15
+126890,2025-12-15 19:00:19,0.00%,8.75MB,15.98MB,0.11%,0.00 MB/s,0.00 MB/s,0.00 MB/s,0.00 MB/s,python,sleeping,/mnt/d/code/listen_py,/home/jiyuhang/miniconda3/envs/testpy1/bin/python3.12,2025-12-15 19:00:15
+126890,2025-12-15 19:00:21,0.00%,8.75MB,15.98MB,0.11%,0.00 MB/s,0.00 MB/s,0.00 MB/s,0.00 MB/s,python,sleeping,/mnt/d/code/listen_py,/home/jiyuhang/miniconda3/envs/testpy1/bin/python3.12,2025-12-15 19:00:15
+126890,2025-12-15 19:00:24,0.00%,94.83MB,101.82MB,1.21%,0.00 MB/s,0.00 MB/s,0.00 MB/s,0.00 MB/s,python,sleeping,/mnt/d/code/listen_py,/home/jiyuhang/miniconda3/envs/testpy1/bin/python3.12,2025-12-15 19:00:15

Разлика између датотеке није приказан због своје велике величине
+ 490 - 0
results/pyspy_output.svg


+ 43 - 0
test/test_script.py

@@ -0,0 +1,43 @@
+#!/usr/bin/env python3
+"""
+用于性能测试的简单脚本示例
+"""
+
+import time
+import math
+
+def cpu_intensive_task():
+    """模拟CPU密集型任务"""
+    result = 0
+    for i in range(1000000):
+        result += math.sqrt(i) * math.sin(i)
+    return result
+
+def io_simulation_task():
+    """模拟IO操作"""
+    time.sleep(0.1)
+    return "IO simulation completed"
+
+def memory_intensive_task():
+    """模拟内存密集型任务"""
+    big_list = []
+    for i in range(100000):
+        big_list.append([j for j in range(100)])
+    return len(big_list)
+
+def main():
+    print("开始执行测试任务...")
+    time.sleep(3)
+    # 执行各种类型的任务
+    result1 = cpu_intensive_task()
+    print(f"CPU密集型任务完成: {result1}")
+    time.sleep(2)
+    result2 = io_simulation_task()
+    print(result2)
+    time.sleep(2)
+    result3 = memory_intensive_task()
+    print(f"内存密集型任务完成: {result3}")
+    time.sleep(2)
+    print("所有任务执行完毕")
+if __name__ == "__main__":
+    main()

Неке датотеке нису приказане због велике количине промена