一个工控软件,每秒向一个SQLite 数据库读最新的采样数据,数据实时展示成曲线图,并且放到一个 WPF ListView 控件里。
运行一个晚上,大约5W个采样。内存8G,入门级工控机,机械硬盘(说用SSD的不用考虑了,公司里的原话是:“不可能给你配SSD,死了这条心”),运行一晚后,内存占用有5G多。
但是点开这个程序后,磁盘灯一直亮,超过10分钟了,窗体主界面一直卡着不动。
有什么优化建议?
可能是占内存太多或ListView控件绑定的数据太多导致的,因为我看你说“并且放到一个 WPF ListView 控件里”
这个我也怀疑过
但很奇怪的是,如果关闭这个进程,并且重新打开,甩有的数据全部重新加载过了,它又运行得很流畅了
我是怀疑是不是操作系统发现这个进程一直没有活动,就把它变成后台进程,并且很多内存中的数据都转存到磁盘上了,而当每二天早上有人过来激活它时,想要重新恢复到原来的状态时就卡死了
@血狼一族: 不知道了,反正我觉得控件上绑定大量数据肯定不是最好的设计。我觉得可以分页。只显示最新的,如果想看旧的,可以点“上一页”然后再加载
@血狼一族: 还有你说的那个曲线控件,是不是每条数据都要绘制上去,会不会数据太多卡住了?
@会长: 这样的设计是需求决定的,要是允许翻页,哪来这么些个破事儿
@血狼一族: 那就是不合理的需求
看内存占用挺高的,是不是实时展示的曲线没有及时释放之前的数据。
可以考虑展示的曲线中只展示最近N分钟的数据,否则数据越来越多,会导致卡住
其实还有其它的一些数据展示,类似于最高/最低/平均温度、电压、功率之类的,数据量不大,一般不怀疑它们。
目前的现象是,一直让它在前端展示时,没毛病,因为数据就在数据库里,把展示数据的程序打开,一次性全部读进来无论是曲线图还是 ListView,都还流畅,也没太大压力。或者现场让它运行,人有三五分钟,二三十分钟去撩拨几下,程序运行也没毛病。但是让它独自跑通宵,十来个小时不去碰它,第二天鼠标点它时,就卡死了。卡死之前,它的内存占用率不算高,有时不到1G,有时超过1G多一点,但只要一点它,内存占用率就不断增加,硬盘灯不断亮,看任务管理器,操作系统的磁盘是100%。
@血狼一族: 磁盘占用高的话,先找出代码中哪些部分是和磁盘读写有关的,重点分析分析这部分代码
代码写得有问题,首先不可能每秒写1w个点。
一晚上5w / 10h ,那么平均每秒3个点,根本不存在计算机瓶颈。
难道你每秒 完整读一次,然后刷控件,然后还不知道Dispose 和 GC。
5W采样点,10个小时,平均每秒1.3个采样,何况有一个多小时,差不多一秒一个点。
数据也不是每次全部读取,而是读最新的。 ListView 的 DataConext 绑定到一个 ObservableList 里,通过向这个队列尾追加采样点数据,ListView 自动渲染界面。
你曲线要全部展示完吗?只展示最新的段。可能是你累计展示多了的原因
图表完全展示应该问题不大。因为我是嵌入了一个 WebView2 控件,然后用 eChart 去展示它们,这样可以在任务管理器里看到 WebView2 占用的资源,内存、CPU的占用率都不高。
@血狼一族: web类控件都是占用内存特大, 不会自动释放的,得关闭程序才会释放
建议不要用这类控件,上面的图, 自己用draw画一个
@风浪: 画过了,最早就是自己画的,但很难满足要求,Bug还多,所以才改用 WebView2 + echarts 的。这个问题其实不大,现在来看展示1万个点没什么压力。就算有压力,我也可以使用摘要的方式移掉一些点。比如最大设置1万个点,如果超过1万点,就开始每两个点中取一个,使总点数不超过1万。这样曲线看起来和原来应该差不多。
在任务管理器中找到wpf进程转存储,使用windbg去分析一下吧
解决了两个问题
一是通宵运行后,第二天查看时,硬盘读个不停的问题。这是因为工控机的电源管理,默认了设置20分钟关闭硬盘,第二天就恢复不起来了。现在设置了从不关闭硬盘,通宵运行之后没毛病了
二是取消了自动刷新数据,以前每秒一次刷新,现在改为全手动刷新,客户也能接受。
很明显是没有使用数据虚拟化,导致数据一直加载在内存,没有释放啊