【实时】DevExpress内存监视
前言
在做项目的时候,我们有时候需要检测项目的内存占用情况,有时候是检测内存泄露~,有时候是查看某段代码执行前后的内存对比,以方便找出问题并以解决。
内存泄漏也称作“存储渗漏”,用动态存储分配函数动态开辟的空间,在使用完毕后未释放,结果导致一直占据该内存单元。直到程序结束。(其实说白了就是该内存空间使用完毕之后未回收)即所谓内存泄漏。-百度百科
前几天做项目的时候就遇到这种情况,项目是winform开发,大数据压缩、解压和绑定的时候,内存飙升的很快。虽然通过Windows任务管理器可以查看到进程的内存使用情况,但只是数值的体现,想要的效果:

这种波线图可以直观的体现出程序的CPU使用情况,找了一下关于内存的,虽然在资源监视器中有内存的使用情况,但是并不是我想要的,也在网上找了下内存监视程序,找了大半天也没找到。
自己动手,丰衣足食。
DevExpress安装问题
这里在多说句,其实用DevExpress也是没办法,网上找了好多图形控件,但都不是我想要的,虽然DevExpress比较大,但是大有大的好处,那就是功能很强大。
关于DevExpress的安装写了一篇文章《DevExpress控件安装、汉化使用教程》,大家可以参考下。
在安装完之后记得要安装DevExpress.Patch.13.1.5.exe这个补丁包,不然开发的程序每次都会弹出:

还有一点就是安装完卸载的时候,一定要正确的卸载,有次我正在卸载的时候强制关机了,重新开机安装的时候,就会出现这种情况:

虽然程序已经卸载,但还是提示模块已经安装,程序已经被破坏了,然后我就用软媒 - Win7优化大师(我认为是比较好的清理工具),深度清理了下垃圾文件和注册表,但是发现还是不行,肯定注册表文件没有清理干净,有点想要重装系统的冲动,单仅仅是冲动,没有行动,毕竟重装完系统要那么多的软件要重新安装,没办法就手动清理注册表吧,搜寻“DevExpress”有关的注册表,那不是一般的多啊,还有些是GUID生成的:

一条一条的删啊,也不知道删了多少条,但我记得肯定没删完,我就是试了下重装,发现可以了。
做事要有耐心。
实现
以上废话说的有点多,关于DevExpress的教程真的很少(中文),因为DevExpress太庞大了,只能通过DevExpress提供的示例程序去学习,实现上面波形图在DevExpress中有个控件叫SwiftPlotDiagram,位置在DevExpress.XtraCharts.v13.1.dll,使用DevExpress实现图形程序必须包含在ChartControl控件下。
我们先看下设计器:

除去实现内存监控这个程序,我们只考虑波形图,要实现一般有几个基本元素:
- 坐标(SeriesPoint)
- 时间刻度(TimeInterval)
- 走势线(RegressionLine)
RegressionLine翻译是回归线的意思,就是一个总的大致走势方向,我称作走势线,只是个叫法不同。
上面元素中坐标最重要,明白了元素我们看下代码:
private const int interval = ;
private double value = 10.0;
RegressionLine Regression { get { return GetRegressionLine(Series); } }
private int TimeInterval
{
get
{
return Convert.ToInt32(nud_Interval.Value);
}
}
private Series Series
{
get
{
return chartControl.Series.Count > ? chartControl.Series[] : null;
}
}
上面几个字段就不解释了,value是纵坐标的值,也就是内存值,Series英文翻译是串联的意思,这边表示的是坐标组成曲线的集合,因为这边我们就画了一个曲线图所以是Series[]。
//获取进程
private void getProcess()
{
foreach (Process item in Process.GetProcesses())
{
cb_Process.Items.Add(item.ProcessName);
}
cb_Process.SelectedIndex = ;
}
//获取下一个坐标值
private double CalculateNextValue(double value)
{
Process process = Process.GetProcessesByName(cb_Process.Text)[];
return process.PrivateMemorySize64/1024.0;
}
getProcess()方法是获取本地线程集合填充到下拉列表中,CalculateNextValue()方法是更新纵坐标的值,也就是内存值,这个方法在timer事件中调用。
我们看下timer事件代码:
//timer事件
private void timer_Tick(object sender, EventArgs e)
{
if (Series == null )
{
return;
}
var argument = DateTime.Now;
//一个刻度需要画的坐标
var pointsToUpdate = new SeriesPoint[interval];
for (var i = ; i < interval; i++)
{
pointsToUpdate[i] = new SeriesPoint(argument, value);
argument = argument.AddMilliseconds();
UpdateValues();
}
//添加坐标
AddPoints(Series, pointsToUpdate);
var minDate = argument.AddSeconds(-TimeInterval);
//重新设置X轴MinMaxValues
var diagram = chartControl.Diagram as SwiftPlotDiagram;
if (diagram != null && diagram.AxisX.DateTimeScaleOptions.MeasureUnit == DateTimeMeasureUnit.Millisecond)
{
diagram.AxisX.Range.SetMinMaxValues(minDate, argument);
}
}
timer事件主要做个三个工作,一是根据设置好的interval获取每个刻度的内存值,然后添加到Points数组中,interval的值越大,画出的波线图越精细,下面就是把Points数组的坐标值加到Series中,最后把X轴的最大小值设置下,以实现动态的效果,需要注意的是:
diagram.AxisX.Range.SetMinMaxValues(minDate, argument);
这句代码的意思不是设置整个X轴的最大小值,而是这个刻度下的最大小值,大家可以把这段代码注释下看下效果就知道了,可以看出时间刻度是一样的,并没有清除叠加。

关于X轴-时间轴,我们可以在设计其中可以设置:
swiftPlotDiagram1.AxisX.DateTimeScaleOptions.GridAlignment = DevExpress.XtraCharts.DateTimeGridAlignment.Millisecond;
swiftPlotDiagram1.AxisX.DateTimeScaleOptions.MeasureUnit = DevExpress.XtraCharts.DateTimeMeasureUnit.Millisecond;
swiftPlotDiagram1.AxisX.Label.DateTimeOptions.Format = DevExpress.XtraCharts.DateTimeFormat.Custom;
swiftPlotDiagram1.AxisX.Label.DateTimeOptions.FormatString = "mm:ss";
series1.ArgumentScaleType = DevExpress.XtraCharts.ScaleType.DateTime;
上面是设置X轴-时间刻度为毫秒,下面是设置显示的格式,最下面代码的意思是设置曲线画图刻度的格式是DateTime格式,也就是上面SeriesPoint的argument。
下面关于图标标注的设置就是图形上面的标注PrivateMemory,因为所有的图形控件都集成在ChartControl中,只要找到设置起来很方便:
this.chartControl.Legend.AlignmentHorizontal = DevExpress.XtraCharts.LegendAlignmentHorizontal.Left;
this.chartControl.Legend.AlignmentVertical = DevExpress.XtraCharts.LegendAlignmentVertical.TopOutside;
this.chartControl.Legend.Direction = DevExpress.XtraCharts.LegendDirection.LeftToRight;
this.chartControl.Legend.Visible = true;
series1.Name = "PrivateMemory";
regressionLine1.Name = "Regression Line";
swiftPlotSeriesView1.Indicators.AddRange(new DevExpress.XtraCharts.Indicator[] {
regressionLine1});
series1.View = swiftPlotSeriesView1;
this.chartControl.SeriesSerializable = new DevExpress.XtraCharts.Series[] {
series1};
上面设置标注显示格式,设置名称只要设置series的name属性就行,不需要重新绑定,因为Legend是集成到chartControl中的,设置好后把series添加到chartControl中就可以显示了,如果要显示多个线性,只要再添加series即可。
关于刻度标示的设置:
swiftPlotDiagram1.AxisX.Title.Text = "时间";
swiftPlotDiagram1.AxisX.Title.Visible = true;
swiftPlotDiagram1.AxisY.Title.Text = "内存大小(KB)";
swiftPlotDiagram1.AxisY.Title.Visible = true;
最后关于走势线RegressionLine,因为是集成在chartControl,用的时候只要指示需要体现的series,添加到Indicators集合中就可以了,看下代码:
regressionLine1.Name = "Regression Line";
swiftPlotSeriesView1.Indicators.AddRange(new DevExpress.XtraCharts.Indicator[] {
regressionLine1}); //获取走势线
private static RegressionLine GetRegressionLine(Series series)
{
if (series != null)
{
var swiftPlotView = series.View as SwiftPlotSeriesView;
if (swiftPlotView != null)
{
foreach (Indicator indicator in swiftPlotView.Indicators)
{
var regressionLine = indicator as RegressionLine;
if (regressionLine != null)
{
return regressionLine;
}
}
}
}
return null;
}
说了那么多,我们看下最后实现的效果(20毫秒,录制的比较卡):

完整代码:
using System;
using DevExpress.DXperience.Demos;
using DevExpress.XtraCharts;
using System.Diagnostics; namespace MemoryMonitor
{
public partial class ChartDemoRealtimeChart : TutorialControlBase
{
private const int interval = ;
private double value = 10.0;
RegressionLine Regression { get { return GetRegressionLine(Series); } }
private int TimeInterval
{
get
{
return Convert.ToInt32(nud_Interval.Value);
}
}
private Series Series
{
get
{
return chartControl.Series.Count > ? chartControl.Series[] : null;
}
}
#region 界面事件
//实例化事件
public ChartDemoRealtimeChart()
{
InitializeComponent();
Regression.Visible = false;
getProcess();
}
//timer事件
private void timer_Tick(object sender, EventArgs e)
{
if (Series == null )
{
return;
}
var argument = DateTime.Now;
//一个刻度需要画的坐标
var pointsToUpdate = new SeriesPoint[interval];
for (var i = ; i < interval; i++)
{
pointsToUpdate[i] = new SeriesPoint(argument, value);
argument = argument.AddMilliseconds();
UpdateValues();
}
//添加坐标
AddPoints(Series, pointsToUpdate);
var minDate = argument.AddSeconds(-TimeInterval);
//重新设置X轴MinMaxValues
var diagram = chartControl.Diagram as SwiftPlotDiagram;
if (diagram != null && diagram.AxisX.DateTimeScaleOptions.MeasureUnit == DateTimeMeasureUnit.Millisecond)
{
diagram.AxisX.Range.SetMinMaxValues(minDate, argument);
}
}
//开始/暂停
private void btnStart_Click(object sender, EventArgs e)
{
timer.Enabled = !timer.Enabled;
btnStart.Text = timer.Enabled ? "暂停" : "开始";
}
//显示走势线
private void cb_RegressionLine_CheckedChanged(object sender, EventArgs e)
{
if (Regression != null)
Regression.Visible = cb_RegressionLine.Checked;
}
//选择需要监控的进程
private void cb_Process_SelectedIndexChanged(object sender, EventArgs e)
{
Series.Points.Clear();
}
#endregion
#region Some方法
//获取下一个坐标值
private double CalculateNextValue(double value)
{
Process process = Process.GetProcessesByName(cb_Process.Text)[];
return process.PrivateMemorySize64/1024.0;
}
//更新坐标值值
private void UpdateValues()
{
value = CalculateNextValue(value);
}
//添加坐标
private void AddPoints(Series series, SeriesPoint[] pointsToUpdate)
{
if (series.View is SwiftPlotSeriesViewBase)
{
series.Points.AddRange(pointsToUpdate);
}
}
//获取走势线
private static RegressionLine GetRegressionLine(Series series)
{
if (series != null)
{
var swiftPlotView = series.View as SwiftPlotSeriesView;
if (swiftPlotView != null)
{
foreach (Indicator indicator in swiftPlotView.Indicators)
{
var regressionLine = indicator as RegressionLine;
if (regressionLine != null)
{
return regressionLine;
}
}
}
}
return null;
}
//获取进程
private void getProcess()
{
foreach (Process item in Process.GetProcesses())
{
cb_Process.Items.Add(item.ProcessName);
}
cb_Process.SelectedIndex = ;
}
#endregion
}
}
示例程序下载:MemoryMonitor.rar
后记
swiftPlotDiagram只是chartControl的冰山一角,chartControl只是DevExpress的冰山一角,DevExpress只是扩展控件的冰山一角,扩展控件只是。。。
学无止境,不得不学。
【实时】DevExpress内存监视的更多相关文章
- JVM内存监视手段和内存溢出解决方案
引言 本文仅关注一些常见的虚拟机内存监视手段,以及JVM运行时数据区各个部分内存溢出的发生和对应的解决方案,总体来说属于概括性总结,涉及相对不是很深入,目的是让自己和其它初学者有一个框架性.概念性的了 ...
- JVM总结-内存监视手段及各区域内存溢出解决
转载:https://blog.csdn.net/xuqu_volition/article/details/53786096 引言 本文仅关注一些常见的虚拟机内存监视手段,以及JVM运行时数据区各个 ...
- Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)
websocketd 是WebSocket守护进程,它负责处理WebSocket连接,启动您的程序来处理WebSockets,并在程序和Web浏览器之间传递消息. 安装:websocketd wget ...
- smem – Linux 内存监视软件
导读 Linux 系统的内存管理工作中,内存使用情况的监控是十分重要的,在各种 Linux 发行版上你会找到许多这种工具.它们的工作方式多种多样,在这里,我们将会介绍如何安装和使用这样的一个名为 sm ...
- DSAPI 获取实时统计信息CPU/内存/硬盘/网络
有时,我们需要获取当前计算机中CPU.内存.硬盘.网络等实时信息,如下图:\ 要实现上述几项信息的获取,通常需要使用Timer控件来间隔获取,以便刷新最新的数据. 本示例中,放一个Timer控件,放一 ...
- 20个Linux系统监视工具
需要监视Linux服务器的性能?试试这些内置的命令和一些附加的工具吧.大多数Linux发行版都集成了一些监视工具.这些工具可以获取有关系统活动的信息的详细指标.通过这些工具,你可以发现产生系统性能问题 ...
- 在 Linux 平台中调试 C/C++ 内存泄漏方法(转)
由于 C 和 C++ 程序中完全由程序员自主申请和释放内存,稍不注意,就会在系统中导入内存错误.同时,内存错误往往非常严重,一般会带来诸如系统崩溃,内存耗尽这样严重的后果.本文将从静态分析和动态检测两 ...
- Linux系统基本的内存管理知识讲解
内存是Linux内核所管理的最重要的资源之一.内存管理系统是操作系统中最为重要的部分,因为系统的物理内存总是少于系统所需要的内存数量.虚拟内存就是为了克服这个矛盾而采用的策略.系统的虚拟内存通过在各个 ...
- Linux系统监视工具
转自 http://bbs.51cto.com/thread-971896-1.html # 1: top – 查看活动进程的命令TOP工具能够实时显示系统中各个进程的资源占用状况.默认情况 ...
随机推荐
- gulp-less解决遇到错误停止执行task
来龙去脉 在用less+gulp开发时,有时候代码还没写完整,不小心保存了一下,然后gulp就开始执行gulp-less的task. 但是代码是有问题的,这时候会输出一个Potentially unh ...
- Xamarin的不归路-使用Gorilla Player实时预览XAML
搞了一天,才安装好,记录一下遇到的坑,为大家节约些时间. 一.下载软件 软件下载地址:http://gorillaplayer.com/ 没有FQ前用360极速浏览器和迅雷下载了好多次都失败了.用了蓝 ...
- linux开启FTP以及添加用户配置权限,只允许访问自身目录,不能跳转根目录
1.切换到root用户 2.查看是否安装vsftp,我这个是已经安装的. [root@localhost vsftpd]# rpm -qa |grep vsftpd vsftpd--.el7_2.x8 ...
- *HDU1850 博弈
Being a Good Boy in Spring Festival Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32 ...
- 微信小程序demo汇总
wechat-app-music fenda-mock Wa-UI wx-query weapp-artand WeiXin-SmallApps-Information weapp-wechat-zh ...
- 华为oj 购物单
这两天断断续续敲完这个(放假的时候比较懒),一次成功有点小激动(●'◡'●) 不过貌似从第一次打开开始计时..... 这道题目很像01背包,我将附件与它们的主件绑定(就是link起来)然后套用动态规 ...
- eclipse构建maven的web项目
如果以后要创建maven的web项目,可以参考这个链接 http://blog.csdn.net/smilevt/article/details/8215558/
- CSS基础篇之选择符2
属性选择符: 选择符 版本 描述 E[att] CSS2 选择具有att属性的E元素. E[att="val"] CSS2 选择具有att属性且属性值等于val的E元素. E[at ...
- ios培训机构排名
移动互联网的时代,智能手机的作用已经无所不在,APP在人们的生活中也起到了非常重要的作用,iOS开发行业同样受到越来越多人的关注,更多的人选择参加iOS培训机构来加入这个行列,而如何选择一个真正可以学 ...
- PostgreSQL 与 MySQL 相比,优势何在?
一. PostgreSQL 的稳定性极强, Innodb 等引擎在崩溃.断电之类的灾难场景下抗打击能力有了长足进步,然而很多 MySQL 用户都遇到过Server级的数据库丢失的场景——mysql系统 ...