背景介绍

笔者之前接到一个需求,需要在WPF上实时显示病人实时的生理信号(心电图等)。团队开发,需求很快做完了(Unit test 效果图如下)

但是后来发布到产品上发现,资源占用比本机的要大。本地监控后,发现随着时间推移内存和Page Faults 都在增长,如果在产品上长期(几个月甚至更长时间)运行可能会导致性能问题。那么就要做性能优化了。

Page Faults

MSDN:The number of times that data had to be retrieved from disk for this process because it was not found in memory. This value is accumulated from the time the process is started.
Page faults/sec is the rate of page faults over time.

Page faults:不能说明什么问题,但是证明内存读写频率较高

A memory page fault occurs when requested data is not found in memory. The system generates a fault, which normally indicates that the system looks for data in the paging file. In this circumstance, however, the missing data is identified as being located within an area of memory that cannot be paged out to disk. The system faults, but cannot find, the data and is unable to recover. Faulty hardware, a buggy system service, antivirus software, and a corrupted NTFS volume can all generate this type of error.

当在内存中找不到请求的数据时,会发生内存页错误。系统生成一个故障,通常表示系统在分页文件中查找数据。然而,在这种情况下,丢失的数据被标识为位于无法分页到磁盘的内存区域内。系统出现故障,但无法找到数据,无法恢复。有故障的硬件、有缺陷的系统服务、防病毒软件和损坏的NTFS卷都会产生此类错误。

性能优化

初始方案:我们最开始是用WPF内置的Polyline来绘图的。

查看MSDN 后发现Polyline是比较冗余的,WPF中图像渲染是Visual 类提供的。

WPF主要类型的职责

Visual: Provides rendering support in WPF, which includes hit testing, coordinate transformation, and bounding box calculations.

UIElement: 在Visual基础上 主要增加了可以响应用户输入(包括通过处理事件路由或命令路由控制输入的发送位置)以及可以引发通过元素树传递路由的路由事件。

更详细内容可以查看MSDN ,就不一一列举了。

在绘制生理信号这个case中 只需要图形可以实时渲染到container中即可,只需要Visual类型提供的功能。

改进后方案

发现了DrawingVisual 这个类型更加的轻量级,没有Polyline 类型继承的冗余属性。
优化Demo:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;namespace MVVMDemoTest.DrawVisual
{// Create a host visual derived from the FrameworkElement class.// This class provides layout, event handling, and container support for// the child visual objects.public class MyVisualHost : FrameworkElement{// Create a collection of child visual objects.private VisualCollection _children;public MyVisualHost(){_children = new VisualCollection(this);_children.Add(CreateDrawingVisualRectangle());//_children.Add(CreateDrawingVisualText());//_children.Add(CreateDrawingVisualEllipses());// Add the event handler for MouseLeftButtonUp.this.MouseLeftButtonUp += new System.Windows.Input.MouseButtonEventHandler(MyVisualHost_MouseLeftButtonUp);}// Create a DrawingVisual that contains a rectangle.private DrawingVisual CreateDrawingVisualRectangle(){DrawingVisual drawingVisual = new DrawingVisual();// Retrieve the DrawingContext in order to create new drawing content.DrawingContext drawingContext = drawingVisual.RenderOpen();// Create a rectangle and draw it in the DrawingContext.Rect rect = new Rect(new System.Windows.Point(160, 100), new System.Windows.Size(320, 80));drawingContext.DrawLine(new Pen(Brushes.Yellow, 2), new Point(100,100),new Point(300,100) );drawingContext.DrawRectangle(Brushes.LightBlue, (System.Windows.Media.Pen)null, rect);drawingContext.DrawText(new FormattedText("this is a test",CultureInfo.GetCultureInfo("en-us"),FlowDirection.LeftToRight,new Typeface("Verdana"),32,Brushes.Black),new Point(200,200));var StreamGeometry = new StreamGeometry();StreamGeometry.Clear();var points = new List<Point>(){new Point(20,20),new Point(40,3),new Point(60,200),new Point(0,0)};using (var ctx = StreamGeometry.Open()){ctx.BeginFigure(new Point(0,0), false, false);ctx.PolyLineTo(points, true, false);}drawingContext.DrawGeometry(Brushes.Yellow,new Pen(Brushes.Black,2), StreamGeometry);// Persist the drawing content.drawingContext.Close();return drawingVisual;}// Provide a required override for the VisualChildrenCount property.protected override int VisualChildrenCount{get { return _children.Count; }}// Provide a required override for the GetVisualChild method.protected override Visual GetVisualChild(int index){if (index < 0 || index >= _children.Count){throw new ArgumentOutOfRangeException();}return _children[index];}// Capture the mouse event and hit test the coordinate point value against// the child visual objects.void MyVisualHost_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e){// Retrieve the coordinates of the mouse button event.System.Windows.Point pt = e.GetPosition((UIElement)sender);// Initiate the hit test by setting up a hit test result callback method.VisualTreeHelper.HitTest(this, null, new HitTestResultCallback(myCallback), new PointHitTestParameters(pt));}// If a child visual object is hit, toggle its opacity to visually indicate a hit.public HitTestResultBehavior myCallback(HitTestResult result){if (result.VisualHit.GetType() == typeof(DrawingVisual)){if (((DrawingVisual)result.VisualHit).Opacity == 1.0){((DrawingVisual)result.VisualHit).Opacity = 0.4;}else{((DrawingVisual)result.VisualHit).Opacity = 1.0;}}// Stop the hit test enumeration of objects in the visual tree.return HitTestResultBehavior.Stop;}}
}

总结

WPF提供的功能丰富强大,但是由于提供的功能过多,导致有一定的性能问题,这是已知。因此我们在设计和使用WPF的时候,一定要尽可能使用轻量级的模块,必要时,可以自己继承的方式完成。

WPF 性能优化-高刷新绘图相关推荐

  1. WPF 性能优化建议

    本章讲述:WPF 性能优化建议 20180930 WPF性能优化问题:运行软件发现CPU使用率很大(80%-95%),程序中含有委托,线程,定时器的处理,之前优化时,主要优化线程和定时器相关线程方面的 ...

  2. 闲话WPF之二六(WPF性能优化点)

    在建立漂亮UI的同时,我们还需要关注应用程序的性能,WPF尤其如此.下面从MS的文档中总结出了一些有用的性能优化点.在实际编写的过程中,可以参考.这个Post非完全原创,是根据一些文档总结出来的. 1 ...

  3. mysql性能优化和高可用架构实践pdf_实践大于一切!Alibaba最新MySQL性能优化+高可用架构全彩版PDF...

    本篇的内容将会覆盖MySQL 5. 7数据库体系结构.InnoDB存储引擎.MySQL事务和锁.性能优化.服务器全面优化.性能监控.主从复制,以及PXC集群.MHA自动故障转移群集.MGR组复制.Ke ...

  4. c#+wpf项目性能优化之OutOfMemoryException解密

    近期,使用c#+wpf开发的软件准备正式投入使用了,使用前进行了大量的测试,测试后发现了一些问题,其中最让人头疼的就是软件的性能问题(稳定性). 这里的稳定性具体表现在机器的cpu占有率和内存使用情况 ...

  5. 《MySQL性能优化和高可用架构实践》阅读总结

    文章目录 介绍 第1章 MySQL架构介绍 1.1 MySQL简介 1.2 MySQL主流的分支版本 1.3 MySQL存储引擎 1.4 MySQL逻辑架构 1.5 MySQL物理文件体系结构 第2章 ...

  6. mysql版本不一致会导致uuid_MySQL性能优化和高可用架构建议

    1.主从复制binlog_format要使用row,statement会导致主从数据不一致(基于语句,rand或uuid等函数没法恢复) 2.如果使用binlog恢复数据,标准做法是用mysqlbin ...

  7. nginx应用总结(2)--突破高并发的性能优化

    在日常的运维工作中,经常会用到nginx服务,也时常会碰到nginx因高并发导致的性能瓶颈问题.今天这里简单梳理下nginx性能优化的配置(仅仅依据本人的实战经验而述,如有不妥,敬请指出~) 一.这里 ...

  8. redis抽奖并发_Redis优化高并发下的秒杀性能

    本文内容 使用Redis优化高并发场景下的接口性能 数据库乐观锁 随着双11的临近,各种促销活动开始变得热门起来,比较主流的有秒杀.抢优惠券.拼团等等. 涉及到高并发争抢同一个资源的主要场景有秒杀和抢 ...

  9. oracle书写高质量sql,干货!SQL性能优化,书写高质量SQL语句

    写SQL语句的时候我们往往关注的是SQL的执行结果,但是是否真的关注了SQL的执行效率,是否注意了SQL的写法规范? 以下的干货分享是在实际开发过程中总结的,希望对大家有所帮助! 1. limit分页 ...

最新文章

  1. cinder存储服务
  2. QQ音乐vkey获取,更新播放url
  3. 解决后端返回数据中的大数字问题(使用第三方包json-bigint )
  4. linux tasklet函数,tasklet和work_struct详解
  5. 百行代码制作自己的夸夸语料库,打造聊天机器人
  6. dev编译按钮是灰色_提升 50% 的编译速度!阿里零售通 App 工程提效实践
  7. 【论文阅读-Bidding】《Real-Time Bidding Algorithms for Performance-Based Display Ad Allocation,2011年,微软》...
  8. 虚拟机本来有MySQL,后安装宝塔的MySQL导致MySQL不能启动报错
  9. 廖雪峰的python学习网址
  10. Mysql Cluster集群实现高可用
  11. 求解偏微分方程开源有限元软件deal.II学习--Step 5
  12. timeshift 安装使用说明
  13. Android简单登录界面布局设计
  14. 怎样避免每次运行都启用宏的麻烦
  15. Normalize.css介绍与使用
  16. 职业规划-IOS开发工程师(待完善)
  17. Lol(英雄联盟)自动输入密码
  18. 干趴网络协议:IS-IS 特性
  19. 第九天 03-破解linux密码
  20. 逻辑与和逻辑或,比较

热门文章

  1. JavaWeb仓库管理系统,表弟的棒棒糖到底谁拿了
  2. android代码连接wifi
  3. 如何用命令批量重命名文件
  4. Java语言实现杨辉三角
  5. windows 条件变量
  6. 007 矩阵的秩定义、秩求法、秩的性质
  7. Fireworks MX 2004 制作简单动画 飞鸟翅膀煽动的动画
  8. matlab中图像分割技术之二阈值分割
  9. 通用型RS485通讯电池监测模块的功能及应用方案
  10. 关于张量的一点点小思考