WPF 性能优化-高刷新绘图

这篇具有很好参考价值的文章主要介绍了WPF 性能优化-高刷新绘图。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景介绍

笔者之前接到一个需求,需要在WPF上实时显示病人实时的生理信号(心电图等)。团队开发,需求很快做完了(Unit test 效果图如下)
WPF 性能优化-高刷新绘图
但是后来发布到产品上发现,资源占用比本机的要大。本地监控后,发现随着时间推移内存和Page Faults 都在增长,如果在产品上长期(几个月甚至更长时间)运行可能会导致性能问题。那么就要做性能优化了。
WPF 性能优化-高刷新绘图

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:不能说明什么问题,但是证明内存读写频率较高
WPF 性能优化-高刷新绘图
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来绘图的。
WPF 性能优化-高刷新绘图
查看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类型提供的功能。

改进后方案

WPF 性能优化-高刷新绘图

发现了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的时候,一定要尽可能使用轻量级的模块,必要时,可以自己继承的方式完成。文章来源地址https://www.toymoban.com/news/detail-442810.html

到了这里,关于WPF 性能优化-高刷新绘图的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 性能优化(CPU优化技术)-NEON 介绍

    「发表于知乎专栏《移动端算法优化》」 本节主要介绍基本 SIMD 及其他的指令流与数据流的处理方式,NEON 的基本原理、指令以及与其他平台及硬件的对比。 🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:高性能(HPC)开发基础教程 🎀CSDN主页 发狂的小花 🌄人

    2024年01月24日
    浏览(53)
  • 性能优化(CPU优化技术)-NEON指令介绍

    「发表于知乎专栏《移动端算法优化》」 本文主要介绍了 NEON 指令相关的知识,首先通过讲解 arm 指令集的分类,NEON寄存器的类型,树立基本概念。然后进一步梳理了 NEON 汇编以及 intrinsics 指令的格式。最后结合指令的分类,使用例子讲述 NEON 指令的使用方法。 🎬个人简介

    2024年01月24日
    浏览(44)
  • 性能优化-HVX 指令介绍

    「发表于知乎专栏《移动端算法优化》」 本文主要介绍了 HVX 指令相关的知识,包括 HVX 寄存器相关内容,指令的背景依赖,部分常用 intrinsic HVX 指令。具体指令的详细内容及使用还需阅读 HVX 的指令文档,以及细致的实践操作。 🎬个人简介:一个全栈工程师的升级之路!

    2024年01月25日
    浏览(82)
  • 性能优化-OpenCL 介绍

    「发表于知乎专栏《移动端算法优化》」 本文首先对 GPU 进行了概述,然后着重地对移动端的 GPU 进行了分析,随后我们又详细地介绍了 OpenCL 的背景知识和 OpenCL 的四大编程模型。希望能帮助大家更好地进行移动端高性能代码的开发。 🎬个人简介:一个全栈工程师的升级之

    2024年01月23日
    浏览(36)
  • Nginx 介绍、部署及性能优化

    本文主要内容: 1、Nginx 简介 2、Nginx 搭建及生产环境配置 3、Nginx 性能调优 正向代理: 客户端非常明确要访问的服务器地址,它代理客户 端,替客户端发出请求。比如:FQ (警告⚠️:FQ操作违反相关法律规定,本篇文章仅供 学习参考,切勿盲目FQ)。 反向代理: 均衡分工

    2024年02月04日
    浏览(31)
  • MySQL数据库性能优化技巧介绍

    MySQL是目前最流行和广泛使用的开源关系型数据库之一,随着数据量的增长和访问负载的提高,优化数据库性能变得至关重要,以确保系统能够高效地处理大量的并发请求。本文将记录一些MySQL数据库性能优化的技巧,提高数据库的运行效率,提升系统性能。 对于MySQL,最简单

    2024年02月08日
    浏览(134)
  • 性能优化-OpenCL运行时API介绍

    「发表于知乎专栏《移动端算法优化》」 本文首先给出 OpenCL 运行时 API 的整体编程流程图,然后针对每一步介绍使用的运行时 API,讲解 API 参数,并给出编程运行实例。总结运行时 API 使用的注意事项。最后展示基于 OpenCL 的图像转置代码。在 865 平台下,对于 4096x4096 的 8

    2024年01月24日
    浏览(119)
  • Redis缓存设计与性能优化【缓存和数据库不一致问题,解决方案:1.加过期时间这样可以一段时间后自动刷新 2.分布式的读写锁】

    在大并发下,同时操作数据库与缓存会存在数据不一致性问题 1、双写不一致情况 2、读写并发不一致 解决方案: 1、对于并发几率很小的数据(如个人维度的订单数据、用户数据等),这种几乎不用考虑这个问题,很少会发生缓存不一致, 可以给缓存数据加上过期时间,每隔一

    2024年04月13日
    浏览(54)
  • Golang 程序性能优化利器 PGO 详解(一):简单介绍及使用

    在软件开发过程中,性能优化是不可或缺的一部分。无论是在Web服务、数据处理系统还是实时通信中,良好的性能都是至关重要的。Golang 从1.20版版本开始引入的 Profile Guided Optimization(PGO)机制能够帮助更好地优化 Go 程序的性能。 编译器在编译程序的时候会对程序做很多优

    2024年02月13日
    浏览(36)
  • WPF_3D绘图一

    1.WPF使用DirectX渲染3D元素,它的坐标系如下所示 原点位于呈现区域的中心,x 轴上的正值朝右,但是 y 轴上的正值朝上,z 轴上的正值从原点向外朝向观察者。 2. 3D绘图的四要素 2.1 Viewport3D:视口。 2.2 Camera:相机,提供了三个摄像机类,如下:       1.PerspectiveCamera:透视相机,

    2024年02月03日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包