惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Y
Y Combinator Blog
The GitHub Blog
The GitHub Blog
Vercel News
Vercel News
D
DataBreaches.Net
MongoDB | Blog
MongoDB | Blog
H
Help Net Security
小众软件
小众软件
美团技术团队
T
The Blog of Author Tim Ferriss
爱范儿
爱范儿
D
Docker
Martin Fowler
Martin Fowler
大猫的无限游戏
大猫的无限游戏
博客园 - 聂微东
Blog — PlanetScale
Blog — PlanetScale
H
Hackread – Cybersecurity News, Data Breaches, AI and More
罗磊的独立博客
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
V2EX
S
SegmentFault 最新的问题
云风的 BLOG
云风的 BLOG
B
Blog
雷峰网
雷峰网
The Cloudflare Blog

博客园 - 幸福的菜菜

windows下使用ACME申请SSL证书的办法 ElementPlus Radio 实现双击取消选择的效果 Windows10 LTSC版本 无法访问网络中部分的共享文件夹 SqlSugar : date绑定到XX失败,可以试着换一个类型,或者使用ORM自定义类型实现 VisualStudio Debug模式突然变慢 Visual Stadio 编译提示 The BaseOutputPath/OutputPath property is not set for project ... node-sass编译不通过, 提示 “checking for Python executable "python2" in the PATH” c# async await的使用方式及为啥要用它 winform 实现对usb热拔插的监听 Laravel The only supported ciphers are AES-128-CBC and AES-256-CBC with the correct key lengths Wampserver 配置端口可访问服务 git credential for windows 总是弹出的问题 如何用B表的数据,更新A表的值 WampServer部署https 服务的过程 PHP 命名空间冲突解决方式 Windows下 Docker 简单部署 Django应用 C#实现后台格式化U盘的功能 Winform 实现断点续传的思路及代码 WAMPServer ServerName has syntax error 的问题(阿里云服务器上)
winform绘图与前端canvas绘图效率对比
幸福的菜菜 · 2023-03-20 · via 博客园 - 幸福的菜菜

先说结论:前端canas的绘图效率更高。

因为项目使用winform的缘故,最近要实现一些波形展示的功能。涉及到绘制,肯定离不开GDI+的内容,但是还有替代的方案吗? 当然是有的,可双用WebView2使用前端的技术去绘制。

那么问题来了,哪一种实现更好呢?所以做了一些测试对比

以下是使用GDI+绘制的方式,使用了双缓存加速,绘制100W条线,速度大概是3.4s左右完全渲染出来

    public partial class DrawMaxPointTestForm : Form
    {
        public DrawMaxPointTestForm()
        {
            InitializeComponent();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            Task.Factory.StartNew(() =>
            {
                Random random = new Random();
                var pen = new Pen(Color.Black, 1);
                Stopwatch sw = new Stopwatch();
                sw.Start();

                var grap = this.CreateGraphics();
                var rect = new Rectangle(0, 0, this.Width, this.Height);
                using (BufferedGraphics bufferedGraphics = BufferedGraphicsManager.Current.Allocate(grap, rect))//创建缓冲 Graphics对象,区域
                {
                    bufferedGraphics.Graphics.Clear(Color.White);

                    List<float> widths = new List<float>();
                    List<float> heights = new List<float>();

                    List<PointF> points = new List<PointF>();
                    for (int i = 0; i < 1000000; i++)
                    {
                        points.Add(new PointF((float)(this.Width * random.NextDouble()), (float)(this.Height * random.NextDouble())));
                    }

                    bufferedGraphics.Graphics.DrawLines(pen, points.ToArray());

                    bufferedGraphics.Render(grap);
                }

                sw.Stop();
                Console.WriteLine(sw.ElapsedMilliseconds);
            });
        }
    }

那使用前端效率怎么样呢?

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

    <p>
        <button onclick="drawCanvas()">绘制图形</button>
    </p>
    <canvas id="drawCanvas" width="1500" height="1500"></canvas>


</body>

<script>

    function drawCanvas() {

        let bound = 1500;
        let canvasDom = document.getElementById("drawCanvas");
        let ctx = canvasDom.getContext("2d");

        ctx.clearRect(0, 0, bound, bound);

        let start = Date.now();
        let widths = [];
        let heights = [];
        ctx.beginPath();
        let x = 0;
        let y = 0;
        let maxCount = 100 * 10000;
        for (let i = 0; i < maxCount; i++) {

            x = Math.random() * bound;
            y = Math.random() * bound;

            ctx.lineTo(x, y);
        }
        ctx.lineWidth = 1;
        ctx.strokeStyle = "blue";
        ctx.stroke();
        ctx.closePath();
        console.log("time consume:", Date.now() - start);
    }

</script>

</html>

100W个点,在控制台输出显示只有

啥?81ms ? 这不可能,因为在界面上明显看到绘图有等待时间的,大约1s左右。

嘿嘿,这个就是chrome的线程优化相关的内容了。因为上面的计时只是把数据API丢给chrome后台去绘制,距离渲染完成还有些时间。即时这样,1s时间也是远超winform GDI+的效率的

但是上面是基于纯chrome测试的,要想把他集成到WebView2中还要考虑多个因素: 

  • 使用WebView2传值的性能损耗,100W个点,从c#传给前端会有性能损失吗?
  • WebView2版本与我所测试的chrome版本不同。(WebView2 所使用的chrome内核版本一定是低于我所测试的版本

如果实际项目应用中,上述两点还是需要测试一下。(虽然对性能影响会很小,不过还是要注意排坑)