import re
from collections import defaultdict
# 检测matplotlib是否可用
try:
import matplotlib.pyplot as plt
has_matplotlib = True
except ImportError:
has_matplotlib = False
def process_log(log_path, api_list_path):
# ================== 初始化数据结构 ==================
max_rss = 0
max_rss_line = 0
# 加载API列表
with open(api_list_path) as f:
monitored_apis = {line.strip() for line in f if line.strip()}
api_stack = []
api_diffs = defaultdict(int)
# LOOP处理
active_loops = {}
loop_diffs = {}
# ================== 正则表达式 ==================
rss_pattern = re.compile(r'RSS\s*[:=]\s*(\d+)\s*(?:kb)?\b', re.I)
api_pattern = re.compile(
r'api\s*[:=]\s*"?(.+?)"?\s+(START|END)\b.*?RSS\s*[:=]\s*(\d+)',
re.I
)
loop_pattern = re.compile(
r'LOOP\s+(\d+)\s+(START|END)\b.*?RSS\s*[:=]\s*(\d+)',
re.I
)
# ================== 处理日志 ==================
with open(log_path) as f:
for line_num, line in enumerate(f, 1):
# 处理最大RSS
if rss_match := rss_pattern.search(line):
current_rss = int(rss_match.group(1))
if current_rss > max_rss:
max_rss, max_rss_line = current_rss, line_num
# 处理API记录
if api_match := api_pattern.search(line):
api_name, state, rss = (x.strip() for x in api_match.groups()[:2]] + [api_match.group(3)])
if api_name in monitored_apis:
rss = int(rss)
if state.upper() == 'START':
api_stack.append( (api_name, rss) )
elif state.upper() == 'END':
if api_stack and api_stack[-1][0] == api_name:
start_api, start_rss = api_stack.pop()
api_diffs[api_name] += rss - start_rss
# 处理LOOP记录
if loop_match := loop_pattern.search(line):
loop_id, state, rss = loop_match.groups()
loop_id, rss = int(loop_id), int(rss)
if state.upper() == 'START':
active_loops[loop_id] = rss
elif state.upper() == 'END' and loop_id in active_loops:
loop_diffs[loop_id] = rss - active_loops.pop(loop_id)
# ================== 输出结果 ==================
print(f"\n=== 最大RSS值 ===\n{max_rss}kb (行号: {max_rss_line})")
print("\n=== API差值统计 ===")
print("\n".join(f"{k}: {v:+}kb" for k, v in api_diffs.items()) or "无数据")
print("\n=== 循环差值统计 ===")
if loop_diffs:
sorted_loops = sorted(loop_diffs.items())
print("\n".join(f"循环{id}: {diff:+}kb" for id, diff in sorted_loops))
# 可视化处理
if has_matplotlib:
plt.figure(figsize=(10, 5))
ids, diffs = zip(*sorted_loops)
bars = plt.bar(ids, diffs, color=['#4CAF50' if d > 0 else '#F44336' for d in diffs])
plt.title('循环内存差值变化')
plt.xlabel('循环编号'), plt.ylabel('RSS差值 (kb)')
for bar in bars:
yval = bar.get_height()
plt.text(bar.get_x() + bar.get_width()/2, yval, f'{yval:+}kb', ha='center', va='bottom')
plt.grid(axis='y', ls='--')
plt.tight_layout()
plt.savefig('loop_diffs.png')
print("\n图表已保存为 loop_diffs.png")
else:
import csv
with open('loop_diffs.csv', 'w', newline='') as f:
writer = csv.writer(f)
writer.writerow(['循环编号', '差值(kb)'])
writer.writerows(sorted_loops)
print("\nCSV已保存为 loop_diffs.csv")
else:
print("无有效循环记录")
if __name__ == "__main__":
import sys
if len(sys.argv) != 3:
print("用法: python script.py <日志文件> <API列表文件>")
sys.exit(1)
try:
process_log(sys.argv[1], sys.argv[2])
except Exception as e:
print(f"处理失败: {str(e)}")
sys.exit(1)