如何在Python中获取Scalene Profiler停止后的秒级分析数据?
问题
调用scalene_profiler.stop()后,想通过Python代码获取Scalene性能分析器的输出数据,要求拿到以秒为单位的耗时数据(而非默认报告里的百分比),并自定义格式保存。自己试了一段代码,但结果里出现RunningStats对象,不确定这个方法是否高效,求可行的实现方式。
用户尝试的代码
from scalene import scalene_profiler import time scalene_profiler.start() time.sleep(3) # 我只想要start和stop之间代码行的统计数据,存成字典 scalene_profiler.stop() def ddict2dict(d): if not isinstance(d, dict): return d new_d = {} for k, v in d.items(): if isinstance(v, dict): new_d[k] = ddict2dict(v) else: new_d[k] = v return new_d # 这是我目前试的方法,但这里出现了RunningStats对象,不确定是不是最高效的方式 data = {n: ddict2dict(getattr(scalene_profiler.Scalene._Scalene__stats, n)) for n in scalene_profiler.ScaleneStatistics.payload_contents} print(data)
代码输出
{'max_footprint': 0, 'max_footprint_loc': None, 'current_footprint': 0, 'elapsed_time': 3.0018277168273926, 'alloc_samples': 0, 'total_cpu_samples': 2.391642999999993, 'cpu_samples_c': {'tmp.py': {18: 0.0016429999999999865}}, 'cpu_samples_python': {'tmp.py': {18: 2.389999999999993}}, 'bytei_map': {}, 'cpu_samples': {'tmp.py': 2.391642999999993}, 'cpu_utilization': {'tmp.py': {18: <scalene.runningstats.RunningStats object at 0x1232298d0>}}, 'memory_malloc_samples': {}, 'memory_python_samples': {}, 'memory_free_samples': {}, 'memcpy_samples': {}, 'memory_max_footprint': {}, 'per_line_footprint_samples': {}, 'total_memory_free_samples': 0.0, 'total_memory_malloc_samples': 0.0, 'memory_footprint_samples': [], 'function_map': {}, 'firstline_map': {}, 'gpu_samples': {'tmp.py': {18: 0.0}}, 'total_gpu_samples': 0.0, 'memory_malloc_count': {}, 'memory_free_count': {}}
解决方案
1. 解析RunningStats对象
你看到的RunningStats是Scalene用来存储统计数据的内部类,它包含了均值、中位数、标准差等核心数据。要拿到实际耗时,提取它的mean属性即可——Scalene的采样统计中,均值就是对应代码行的平均耗时(秒级)。
2. 优化数据提取与转换
修改你的字典转换函数,让它自动识别并解析RunningStats对象;同时直接访问Scalene的内部统计实例,不用遍历payload_contents,效率更高。
改进后的代码
from scalene import scalene_profiler from scalene.runningstats import RunningStats import time scalene_profiler.start() time.sleep(3) # 目标代码段 scalene_profiler.stop() def parse_scalene_stats(obj): # 递归处理嵌套字典 if isinstance(obj, dict): return {k: parse_scalene_stats(v) for k, v in obj.items()} # 解析RunningStats对象,提取核心统计值 elif isinstance(obj, RunningStats): return { "平均耗时(秒)": obj.mean, "中位数耗时(秒)": obj.median, "标准差": obj.stddev, "采样次数": obj.count } # 其他数据类型直接返回 else: return obj # 直接获取Scalene内部统计实例 stats_instance = scalene_profiler.Scalene._Scalene__stats # 自定义格式整理需要的耗时数据 custom_stats = { "总运行耗时(秒)": stats_instance.elapsed_time, "总CPU耗时(秒)": stats_instance.total_cpu_samples, "按文件行细分": { "Python代码耗时": parse_scalene_stats(stats_instance.cpu_samples_python), "C扩展代码耗时": parse_scalene_stats(stats_instance.cpu_samples_c), "CPU利用率统计": parse_scalene_stats(stats_instance.cpu_utilization), "GPU耗时统计": parse_scalene_stats(stats_instance.gpu_samples) } } print(custom_stats)
说明
- 效率问题:直接访问Scalene内部的
__stats实例已经是最高效的方式之一——这些数据是Scalene运行时实时采集并存在内存中的,不需要额外计算或IO操作,只是做了对象解析和格式整理。 - 自定义格式:你可以根据需求修改
custom_stats的结构,比如只保留平均耗时(秒)字段,或者按行号汇总所有类型的耗时数据。
内容的提问来源于stack exchange,提问作者Ramsha Siddiqui
相关产品推荐
相关产品推荐

