内容简介:在做性能监控的时候,如果能把监控的CPU和内存增长变化用图表展示出来会比较直观,花了点时间用Python实现了下,来看下怎么用Python绘制Android CPU和内存变化曲线,生成增长曲线图表的PNG图片。一开始想通过采集的CPU和内存数据,导出到Excel生成增长曲线图表。做了下调研,并没有比较好的实现方法。后面看了下用Python来绘制图表实现起来挺容易的,而且Python的学习成本低,语法之类的做过开发的稍微看下就知道怎么用,容易上手。具体实现的效果如下,CPU和内存采集的数据是独立进程的,内存分
在做性能监控的时候,如果能把监控的CPU和内存增长变化用图表展示出来会比较直观,花了点时间用 Python 实现了下,来看下怎么用Python绘制Android CPU和内存变化曲线,生成增长曲线图表的PNG图片。
一、实现效果
一开始想通过采集的CPU和内存数据,导出到Excel生成增长曲线图表。做了下调研,并没有比较好的实现方法。后面看了下用Python来绘制图表实现起来挺容易的,而且Python的学习成本低,语法之类的做过开发的稍微看下就知道怎么用,容易上手。
具体实现的效果如下,CPU和内存采集的数据是独立进程的,内存分三块数据,应用总内存,Native内存和Dalvik内存,如果存在内存泄漏,要么在Native,要么在Dalvik,从图表增长曲线上很容易看出来。
二、具体逻辑实现详解
1. CPU图表的Python实现
import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import json import sys import time import traceback def startDump(): try: cpuData = json.loads(sys.argv[1]) imagePath = sys.argv[2] cpuRateArray = [] timeArray = [] for cpuItem in cpuData: cpuRateArray.append(float(cpuItem["cpuRate"])) timeArray.append((float(float(cpuItem["time"]) - float(cpuData[0]["time"]))/1000)) plt.title("Monitor Cpu Rate") plt.figure(figsize=(10, 8)) plt.tight_layout() plt.plot(timeArray, cpuRateArray, c='red', label='Process CPU') plt.ylabel("CPURate (%)", fontsize=12) plt.xlabel("TimeRange:" + formatTime(float(cpuData[0]["time"])) + ' - ' + formatTime(float(cpuData[len(cpuData) -1]["time"])), fontsize=10) plt.legend() plt.savefig(imagePath) except Exception: print 'exeption occur:' + traceback.format_exc() def formatTime(timeMillis): timeSeconds = float(timeMillis/1000) timelocal = time.localtime(timeSeconds) timeFormat = time.strftime("%Y-%m-%d %H:%M:%S", timelocal) return timeFormat if __name__ == '__main__': startDump()
2. 内存图表的Python实现
import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import json import sys import time import traceback def startDump(): try: memoryData = json.loads(sys.argv[1]) imagePath = sys.argv[2] totalPssArray = [] nativePssArray = [] dalvikPssArray = [] timeArray = [] for memoryItem in memoryData: totalPssArray.append(float(memoryItem["totalPss"])/1024) nativePssArray.append(float(memoryItem["nativePss"])/1024) dalvikPssArray.append(float(memoryItem["dalvikPss"])/1024) timeArray.append((float(float(memoryItem["time"]) - float(memoryData[0]["time"]))/1000)) plt.title("Monitor Memory") plt.figure(figsize=(10, 8)) plt.tight_layout() plt.plot(timeArray, totalPssArray, c='red', label='Total Memory') plt.plot(timeArray, nativePssArray, c='yellow', label='Native Memory') plt.plot(timeArray, dalvikPssArray, c='blue', label='Dalvik Memory') plt.ylabel("Memory (MB)", fontsize=12) plt.xlabel("TimeRange:" + formatTime(float(memoryData[0]["time"])) + ' - ' + formatTime(float(memoryData[len(memoryData) -1]["time"])), fontsize=10) plt.legend() plt.savefig(imagePath) except Exception: print 'exeption occur:' + traceback.format_exc() def formatTime(timeMillis): timeSeconds = float(timeMillis/1000) timelocal = time.localtime(timeSeconds) timeFormat = time.strftime("%Y-%m-%d %H:%M:%S", timelocal) return timeFormat if __name__ == '__main__': startDump()
3. 实现说明
脚本传入的参数有两个,一个是监控的JSON数据字符串值sys.argv[1],一个是保存的图片文件完整路径sys.argv[2]。关于传入的 JSON参数字符串值需要加上单引号修饰 ,否则会导致解析异常,传入的JSON参数也 不能直接是JSON对象 ,必须转化成字符串,示例调用命令如下:
python dump_chart.py '<JSONString>' cpu_chart.png
1)采样CPU示例数据,time是设备的系统时间戳,CPU的占用率的计算可以查看前面写的: Android 性能监控之CPU监控
[ { "time": "1589435564442.279053", "cpuRate": "2.17" }, { "time": "1589435565655.333008", "cpuRate": "3.26" }, { "time": "1589435566954.137939", "cpuRate": "2.52" }, ... ]
2)采样内存示例数据,totalPss、nativePss和dalvikPss值都是从dumpsys meminfo输出的应用内存信息中截取出来的原始数据,对应“TOTAL”、“ Native Heap“、” Dalvik Heap“字段的Pss Total值。内存信息的监控获取参考: Android 性能监控之内存监控
[ { "time": "1589636256923.429932", "totalPss": 177804, "nativePss": 27922, "dalvikPss": 10212 }, { "time": "1589636258236.298096", "totalPss": 178021, "nativePss": 27850, "dalvikPss": 9990 }, { "time": "1589636259525.219971", "totalPss": 177899, "nativePss": 27742, "dalvikPss": 9990 }, ... ]
三、实现过程中遇到的问题
1. load方法使用错误
json.load ()方法使用错误,应该替换成 json.loads ()。
exeption occur:Traceback (most recent call last): File "*******", line 11, in startDump memoryData = json.load(sys.argv[1]) File "/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 287, in load return loads(fp.read(), AttributeError: 'str' object has no attribute 'read'
2. JSON字符串对象入参问题
File "******", line 11, in startDump memoryData = json.loads(sys.argv[1]) File "/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/__init__.py", line 339, in loads return _default_decoder.decode(s) File "/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 364, in decode obj, end = self.raw_decode(s, idx=_w(s, 0).end()) File "/usr/local/Cellar/python@2/2.7.15_1/Frameworks/Python.framework/Versions/2.7/lib/python2.7/json/decoder.py", line 382, in raw_decode raise ValueError("No JSON object could be decoded") ValueError: No JSON object could be decoded
针对Python脚本调用,JSON字符串对象作为入参,传入的JSON字符串对象 需要加单引号处理,比如在JavaScript中示例处理如下:
'\'' + JSON.stringify(cpuRateJSON) + '\''
3. Python需要显示声明参数的类型
在Python中需要指明参数的类型,解析获取到JSON对象中的值之后,Python并不会根据参数来判断是什么类型,需要指明要转化的对象参数类型,比如把系统时间戳转化成float值类型:float(memoryData[0][“time”])
Traceback (most recent call last): File "*******", line 21, in startDump timeArray.append(timeStamp(memoryItem["time"])) File "*******", line 36, in timeStamp timeStamp = float(timeNum/1000) TypeError: unsupported operand type(s) for /: 'unicode' and 'int'
4. 编码导致的异常
SyntaxError: Non-ASCII character '\xe5' in file ******* on line 24, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
如果运行之后报如下的异常,说明是编码出问题,在脚本开头加上编码类型声明:
#!usr/bin/python # -*- coding: utf-8 -*-
5. 保存的文件格式限制
plt.savefig ( image_path ) 保存的文件格式只能是 eps , pdf , pgf , png , ps , raw , rgba , svg , svgz 这些,不支持 jpg 图片的保存。
Traceback (most recent call last): File "/Users/chenwenguan/Documents/AmapAuto/Project/arc-resources/script/performanceMonitor/dump_cpu_chart_image.py", line 23, in startDump plt.savefig(image_path) File "/usr/local/lib/python2.7/site-packages/matplotlib/pyplot.py", line 695, in savefig res = fig.savefig(*args, **kwargs) File "/usr/local/lib/python2.7/site-packages/matplotlib/figure.py", line 2062, in savefig self.canvas.print_figure(fname, **kwargs) File "/usr/local/lib/python2.7/site-packages/matplotlib/backend_bases.py", line 2173, in print_figure canvas = self._get_output_canvas(format) File "/usr/local/lib/python2.7/site-packages/matplotlib/backend_bases.py", line 2105, in _get_output_canvas .format(fmt, ", ".join(sorted(self.get_supported_filetypes())))) ValueError: Format 'jpg' is not supported (supported formats: eps, pdf, pgf, png, ps, raw, rgba, svg, svgz)
6. python-tk 依赖
Traceback (most recent call last): File "*******", line 2, in <module> import matplotlib.pyplot as plt File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/pyplot.py", line 115, in <module> _backend_mod, new_figure_manager, draw_if_interactive, _show = pylab_setup() File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/backends/__init__.py", line 63, in pylab_setup [backend_name], 0) File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/backends/backend_tkagg.py", line 4, in <module> from . import tkagg # Paint image to Tk photo blitter extension. File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/backends/tkagg.py", line 5, in <module> from six.moves import tkinter as Tk File "/home/arc/.local/lib/python2.7/site-packages/six.py", line 203, in load_module mod = mod._resolve() File "/home/arc/.local/lib/python2.7/site-packages/six.py", line 115, in _resolve return _import_module(self.mod) File "/home/arc/.local/lib/python2.7/site-packages/six.py", line 82, in _import_module __import__(name) File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 42, in <module> raise ImportError, str(msg) + ', please install the python-tk package'
缺少 python-tk依赖,执行一下命令安装:
sudo apt-get install python-tk
7. Agg画布初始化配置
Traceback (most recent call last): File "******", line 22, in startDump plt.title("ARC Monitor Memory") File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/pyplot.py", line 1419, in title return gca().set_title(s, *args, **kwargs) File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/pyplot.py", line 969, in gca return gcf().gca(**kwargs) File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/pyplot.py", line 586, in gcf return figure() File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/pyplot.py", line 533, in figure **kwargs) File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/backend_bases.py", line 161, in new_figure_manager return cls.new_figure_manager_given_figure(num, fig) File "/home/arc/.local/lib/python2.7/site-packages/matplotlib/backends/_backend_tk.py", line 1046, in new_figure_manager_given_figure window = Tk.Tk(className="matplotlib") File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1828, in __init__ self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use) TclError: no display name and no $DISPLAY environment variable
在Mac上运行的时候不会出现这个问题,但在Ubuntu环境下运行的时候就报异常了, 官网的解释 如下:
When using Matplotlib versions older than 3.1, it is necessary to explicitly instantiate an Agg canvas
在脚本文件开头显示声明Agg使用:
import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt
8. pyecharts 版本配置问题
如果不是用Python原生方式绘图,而是用pyecharts来绘制图表,要注意下Python版本的匹配。 pyecharts v1.0.0 停止对 Python2.7 , 3.4~3.5 版本的支持和维护,仅支持 Python3.6+。
Traceback (most recent call last): File "*******", line 11, in <module> from pyecharts import options as opts File "/usr/local/lib/python2.7/site-packages/pyecharts/__init__.py", line 1, in <module> from pyecharts import charts, commons, components, datasets, options, render, scaffold File "/usr/local/lib/python2.7/site-packages/pyecharts/charts/__init__.py", line 2, in <module> from ..charts.basic_charts.bar import Bar File "/usr/local/lib/python2.7/site-packages/pyecharts/charts/basic_charts/bar.py", line 17 series_name: str, ^ SyntaxError: invalid syntax
四、参考资料
python 的 pyecharts 绘制各种图表详细(代码)
Parser for command-line options, arguments and sub-commands
扩展阅读:
转载请注明出处:陈文管的博客– Python 绘制Android CPU和内存增长曲线
扫码或搜索: 文呓
微信公众号 扫一扫关注
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 基于react的录音及音频曲线绘制的组件开发
- iOS初级开发学习笔记:贝塞尔曲线的绘制学习
- iOS 沿曲线线性渐变的贝塞尔曲线
- 利用Python中的numpy包实现PR曲线和ROC曲线的计算
- 有趣的椭圆曲线加密
- Flutter 实现平滑曲线折线图
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Data-intensive Text Processing With Mapreduce
Jimmy Lin、Chris Dyer / Morgan and Claypool Publishers / 2010-4-30 / USD 40.00
Our world is being revolutionized by data-driven methods: access to large amounts of data has generated new insights and opened exciting new opportunities in commerce, science, and computing applicati......一起来看看 《Data-intensive Text Processing With Mapreduce》 这本书的介绍吧!
HTML 编码/解码
HTML 编码/解码
html转js在线工具
html转js在线工具