Lightweight, extensible Python performance profiler with minimal overhead
Project description
leaf_perfmon — Python 性能检测库
https://img.shields.io/badge/python-3.7+-blue.svg
https://img.shields.io/pypi/v/perfmon.svg
https://img.shields.io/badge/License-MIT-yellow.svg
https://img.shields.io/badge/code%2520style-black-000000.svg
perfmon 是一个轻量、高性能、可扩展的 Python 性能检测库,提供函数级、代码块级乃至文件级的性能剖析。 它不仅测量执行时间、内存占用、CPU 时间,还支持 I/O 等待时间、锁竞争、异常统计、GC 暂停、HTTP 请求详情、缓存命中率 等高级指标。 通过灵活的采样、阈值过滤、轻量模式,perfmon 能在生产环境中以极低的开销运行。
✨ 核心特性
多粒度检测:
装饰器(函数/方法)、上下文管理器(任意代码块)、文件级执行。
全面指标:
基础:
耗时、CPU 时间、内存分配(增量 & 峰值)、调用次数。
扩展:
文件读写 I/O、锁等待(threading/asyncio)、异常类型统计、GC 暂停、HTTP 请求(requests)、缓存命中率。
资源(需 psutil):
CPU 使用率、进程内存 RSS。
低开销设计:
全局开关(零开销短路)
采样统计(按比例跳过检测)
轻量模式(不记录 min/max/avg)
慢调用阈值(只记录耗时超限的调用)
调用树追踪:
自动记录父子调用关系,直观呈现函数调用图。
异步/生成器友好:
完整支持 async def 和生成器函数。
导出功能:
JSON / CSV 格式导出,便于二次分析或可视化。
零依赖核心:
仅需 Python 标准库(扩展指标需相应库时可选)。
📦 安装
bash
pip install perfmon
可选依赖(用于部分扩展指标):
bash
pip install perfmon[psutil] # 资源监控(CPU 利用率、内存 RSS)
pip install perfmon[requests] # HTTP 请求监控
pip install perfmon[full] # 安装所有扩展
🚀 快速入门
1️⃣ 检测函数 python
import perfmon as pm
import time
@pm.profile(memory=True, cpu=True)
def slow_function():
time.sleep(0.1)
return sum(range(10**6))
slow_function()
pm.report() # 打印性能统计表格
输出示例:
text
名称 调用 总时(s) 平均(s) 最小(s) 最大(s) 总CPU(s) 平均CPU 最小CPU 最大CPU 内存(B) 峰值(B) CPU%
----------------------------------------------------------------------------------------------------------------------------------
slow_function 1 0.10123 0.10123 0.10123 0.10123 0.02001 0.02001 0.02001 0.02001 2048 8192 12.5
2️⃣ 检测代码块 python
with pm.profile_context("数据加载", memory=True):
data = [i**2 for i in range(100000)]
3️⃣ 检测整个脚本 python
pm.profile_file("my_script.py", measure_time=True, memory=True)
pm.report()
4️⃣ 导出 JSON 报告 python
pm.export_json("perf_results.json")
📚 详细使用指南
🔹 装饰器 @profile
python
@pm.profile(
name=None, # 自定义显示名称(默认函数限定名)
measure_time=True, # 测量耗时
memory=False, # 测量内存分配(需 tracemalloc)
cpu=False, # 测量 CPU 时间
lite_mode=None, # 局部轻量模式(覆盖全局)
sample_rate=None, # 局部采样率(覆盖全局)
slow_threshold=None # 局部慢调用阈值(覆盖全局)
)
支持:普通函数、异步函数、生成器函数。
自动记录:调用次数、耗时(若开启)、CPU 时间(若开启)、内存增量/峰值(若开启)、异常类型(若全局配置 monitor_exceptions=True)。
🔹 缓存命中率装饰器 @profile_cache
python
@pm.profile_cache(maxsize=128)
def expensive_func(n):
# 计算结果并缓存
return n * n
自动统计缓存命中/未命中次数。
需通过 pm.configure(monitor_cache=True) 启用记录到 perfmon 统计中。
🔹 上下文管理器 profile_context
python
with pm.profile_context(
name, # 代码块名称
measure_time=True,
memory=False,
cpu=False
):
# 你的代码块
同样支持异步上下文管理器(async with)。
🔹 文件级检测 profile_file
python
pm.profile_file(filename, measure_time=True, memory=False, cpu=False)
执行指定 Python 文件,并将其整体作为一个检测项(名称为 file:文件名)。
🔹 全局配置 configure
python
pm.configure(
# 基本设置
lite_mode=False, # 轻量模式(不记录 min/max/avg)
sample_rate=1.0, # 采样率 0.0~1.0
slow_threshold=0.0, # 慢调用阈值(秒)
record_parent=True, # 记录调用者(调用树)
record_children=True, # 记录子调用(调用树)
resource_monitor=False, # 启用资源监控(需 psutil)
# 扩展指标开关(默认 False)
monitor_io=False, # 文件 I/O 等待时间
monitor_locks=False, # 锁等待时间
monitor_exceptions=False, # 异常类型统计
monitor_gc=False, # GC 暂停时间
monitor_http=False, # HTTP 请求详情(需 requests)
monitor_cache=False # 缓存命中率(配合 @profile_cache)
)
所有开关均可动态修改,且修改后立即生效。
🔹 控制开关
python
pm.enable() # 全局启用检测(默认)
pm.disable() # 全局禁用检测(零开销)
pm.reset() # 清空所有已收集的统计信息
🔹 报告与导出
python
pm.report(sort_by='total_time') # 打印统计表格,可按任意列排序
pm.export_json("path/to/file.json") # 导出全部指标为 JSON
pm.export_csv("path/to/file.csv") # 导出主要指标为 CSV
📊 检测指标详解
指标分类 指标名称 说明 启用方式
基础 调用次数 函数/代码块被执行次数 始终记录
总耗时 / 平均 / 最小 / 最大 墙钟时间(秒) measure_time=True
CPU 时间 进程 CPU 时间(秒) cpu=True
内存增量 执行期间内存分配净增量(字节) memory=True
内存峰值 执行期间内存分配峰值(字节) memory=True
扩展 I/O 读耗时 文件读操作累计耗时(秒) configure(monitor_io=True)
I/O 写耗时 文件写操作累计耗时(秒) 同上
锁等待时间 threading.Lock / asyncio.Lock 获取等待时间 configure(monitor_locks=True)
异常统计 被检测函数抛出的异常类型及次数 configure(monitor_exceptions=True)
GC 暂停时间 垃圾回收器执行耗时(累计) configure(monitor_gc=True)
HTTP 请求 每个 URL 的请求次数、总耗时、状态码分布(需 requests) configure(monitor_http=True)
缓存命中率 被 @profile_cache 装饰的函数命中/未命中次数 configure(monitor_cache=True)
资源 CPU 利用率 执行期间平均 CPU 使用率(%),需 psutil 且 resource_monitor=True resource_monitor=True
进程内存 RSS 进程常驻内存(字节),需 psutil 同上
调用树 父函数数 调用该函数的不同父函数数量 record_parent=True
子调用总数 该函数调用的其他函数总次数 record_children=True
所有扩展指标默认关闭,确保零额外性能开销。仅在需要时显式开启。
🧠 高级功能
1️⃣ 轻量模式 (lite_mode=True)
不再记录 min_time / max_time / min_cpu / max_cpu。
减少约 30% 的内存占用和计算开销。
2️⃣ 采样统计 (sample_rate=0.1)
只有 10% 的调用会被真正检测并记录。
适用于极高频率调用的函数(如每毫秒执行一次)。
3️⃣ 慢调用阈值 (slow_threshold=0.01)
只记录耗时超过 0.01 秒的调用。
自动过滤掉绝大多数快速调用,聚焦性能瓶颈。
4️⃣ 调用树追踪
通过 record_parent / record_children 控制。
在报告表格中显示 父函数数 和 子调用总数,快速识别热点路径。
5️⃣ 资源监控 (需 psutil)
在装饰器/上下文管理器开启时,额外记录 CPU 利用率 (%) 和 进程内存 RSS。
报告表格中增加 CPU% 列。
⚡ 性能开销说明
perfmon 在设计时始终将 低开销 作为首要目标:
全局禁用:pm.disable() 后,所有装饰器直接返回原函数,无任何额外函数调用。
采样:未命中采样的调用不执行任何测量代码。
轻量模式:跳过 min/max 更新,减少数据存储操作。
零依赖核心:基础指标仅使用 Python 内置模块。
在典型场景下(仅开启时间测量),每个函数调用增加约 200400ns 开销。
开启内存检测会增加约 12µs(取决于 tracemalloc)。
扩展指标(I/O、锁等)仅在对应操作发生时产生额外开销。
🧩 扩展指南
perfmon 的设计易于扩展,您可以在 StatEntry 中添加新字段,在 Profiler.record 方法中增加参数,并在适当位置(如补丁函数、装饰器)调用 record 传递新指标。
在 StatEntry.slots 和 init 中添加新字段。
在 Profiler.record 方法中添加对应参数并记录到 stat。
在需要采集数据的地方(如补丁函数、装饰器)调用 _PROFILER.record(...) 传递新指标。
在 export_json 和 export_csv 中添加导出逻辑。
示例:添加“数据库查询耗时”指标可参考 I/O 监控的实现。
📝 完整示例
示例1:综合检测(开启所有扩展) python
import perfmon as pm
import threading, requests, time
pm.configure(
monitor_io=True,
monitor_locks=True,
monitor_exceptions=True,
monitor_gc=True,
monitor_http=True,
monitor_cache=True,
resource_monitor=True
)
@pm.profile(memory=True, cpu=True)
def worker():
# 文件 I/O
with open('/tmp/test.txt', 'w') as f:
f.write('x' * 10000)
# 锁等待
lock = threading.Lock()
lock.acquire()
lock.release()
# HTTP 请求
requests.get('https://httpbin.org/get')
# 异常
try:
1/0
except ZeroDivisionError:
pass
worker()
pm.report()
pm.export_json('full_report.json')
示例2:缓存命中率统计 python
@pm.profile_cache(maxsize=5)
@pm.profile() # 双层装饰器,顺序无妨
def fib(n):
return n if n < 2 else fib(n-1) + fib(n-2)
fib(10)
fib(10) # 第二次命中缓存
print(fib.cache_info()) # 直接查看缓存统计
pm.report() # 缓存命中/未命中会出现在表格中
示例3:采样 + 轻量模式 python
pm.configure(lite_mode=True, sample_rate=0.2)
@pm.profile()
def fast():
for _ in range(1000):
pass
for _ in range(1000):
fast()
pm.report() # 只记录了约200次调用,且无 min/max 列
📋 API 参考
全局函数
函数 描述
profile(...) 函数性能检测装饰器
profile_cache(maxsize=128) 缓存命中率检测装饰器
profile_context(name, ...) 代码块上下文管理器
profile_file(filename, ...) 执行并检测整个 Python 文件
configure(...) 动态修改全局配置
enable() / disable() 全局启用/禁用检测
reset() 清空所有统计数据
report(sort_by='total_time') 打印统计表格
export_json(filepath) / export_csv(filepath) 导出统计数据到文件
配置项详解
配置参数 类型 默认值 说明
lite_mode bool False 轻量模式
sample_rate float 1.0 采样率 0.0~1.0
slow_threshold float 0.0 慢调用阈值(秒)
record_parent bool True 记录调用者
record_children bool True 记录子调用
resource_monitor bool False 启用 psutil 资源监控
monitor_io bool False 监控文件 I/O 耗时
monitor_locks bool False 监控锁等待时间
monitor_exceptions bool False 监控异常类型
monitor_gc bool False 监控 GC 暂停
monitor_http bool False 监控 HTTP 请求(需 requests)
monitor_cache bool False 监控缓存命中率(配合 profile_cache)
🤝 贡献指南
欢迎贡献代码、报告问题或提出新功能建议!
你可以将贡献的代码发给我,Email:FourWaterLeaf@163.com
许可证
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file leaf_perfmon-1.0.0.tar.gz.
File metadata
- Download URL: leaf_perfmon-1.0.0.tar.gz
- Upload date:
- Size: 18.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
97809c753ee49e7fadbb7b5f45e2da55e508e225fca28d811d2aca4935277d56
|
|
| MD5 |
9f61b275e5ead5542a95d446b8c27f01
|
|
| BLAKE2b-256 |
32c5a86fefcb7b6f3716d81618a999f5fbcdcc97504b4016d49a2a9ff4df973d
|
File details
Details for the file leaf_perfmon-1.0.0-py3-none-any.whl.
File metadata
- Download URL: leaf_perfmon-1.0.0-py3-none-any.whl
- Upload date:
- Size: 13.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
841882c49b5a420eeb3f1d9c02e219f8ae9c48e32b17fa33e34704ec53a6da82
|
|
| MD5 |
a751973e0e7e3f1772aa93842bc188d5
|
|
| BLAKE2b-256 |
0dea3225a2b191153f4caa87e1e27b9a5e02f572674f9b2bbadaa4ff1b0d775e
|