0.033秒的艺术 --- 测试程序性能

从HUB75接口到动态扫描:高密度全彩LED点阵屏驱动与树莓派编程实战 LED点阵屏作为一种基础的数字信息显示技术,其核心原理在于通过动态扫描驱动成千上万的像素点。该技术利用人眼视觉暂留效应,通过高速逐行刷新,以有限的驱动电路控制高密度LED阵列,从而实现全彩图像的稳定显示。其技术价值在于提供了高亮度、低功耗且可灵活拼接的可编程显示方案,广泛应用于信息发布、艺术装置和嵌入式人机界面等领域。本文以一块典型的P2.5间距、96x48分辨率的全彩LED模组为例,深入剖析其硬件架构,特别是HUB75并行接口的通信时序和动态扫描逻辑,并详细演示如何基于树莓派和开源驱动库进行软件环境搭建、 阅读详情

这是一系列关于C#与游戏编程性能提示的文章,先来看看如何简单测试一段C#程序的性能。

 0.033秒的艺术 --- 测试程序性能

仅供个人学习使用,请勿转载,勿用于任何商业用途。
  
    交互式的实时3D程序每秒至少渲染30帧图像,才能保证视觉上的平滑,这意味着所有渲染,AI,物理仿真都必须在0.033秒内完成。只有高度优化的代码和算法才能达到这样的要求。如何判断某个算法是否能满足要求,如何比较哪一种算法才是最优的呢?方法有很多,通过丢硬币,撒骰子或者凭感觉猜测等等,不过这些方法通常需要一点点运气的帮助。可惜我不是每天都能有那么好的运气,所以测试是我通常选择的方法。永远不要在测试结束之前作出任何结论。

         几乎所有的测试都以时间和空间代价为主要衡量标准。然而考虑到目前2G内存已经降到了130米以下的价格,所以这里我只关心时间。但是也不要忘了程序和数据所占的空间越小,越能获得缓存所带来的好处,提高命中率。如何来测量一段程序的执行时间呢?啊,你可能马上想到了System.Times和System.Windows.Forms名称空间下的Timer或许还有DateTime。可惜这些计时器的精度都不太理想,通常几十毫秒才更新一次。我们需要高精度的时钟,这将用到2个win32 API:

QueryPerformanceCounter()   这个函数返回硬件支持的高精度计时器的值。
QueryPerformanceFrequency()   返回硬件计时器的频率。

         通过直接访问硬件,这是一个精度非常高的时钟,可以把它的返回值想象为CPU的晶震数和晶振频率。在测试开始和结束的时候,分别查询一次计时器的值,最后相减除以计时器的频率,就能得到精确的时间间隔,以秒为单位,当然,可以进一步转换为任何你觉得方便的单位。可以说目前绝大部分3D游戏的计时系统都是以这2个函数为基础。为了在C#下使用他们,需要通过P/Invoke导入这这两个函数。好了,现在可以这样来测试一段程序的性能:

  1. class Test
  2. {
  3.     [System.Runtime.InteropServices.DllImport("Kernel32.dll")]
  4.     private static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
  5.     [System.Runtime.InteropServices.DllImport("Kernel32.dll")]
  6.     private static extern bool QueryPerformanceFrequency(out long lpFrequency);
  7.     static void Main(string[] args)
  8.     {
  9.        long startTime, endTime, freq;
  10.        QueryPerformanceFrequency(out freq);
  11.        QueryPerformanceCounter(out startTime);
  12.     //Do your test here
  13.        QueryPerformanceCounter(out endTime);            
  14.        Console.WriteLine("frequency: {0:n0}", freq);
  15.        Console.WriteLine("time: {0:n5}s", (endTime - startTime)/(double)freq);
  16.        Console.Read();
  17.     }
  18. }

     也许是这样的代码太过普通和频繁,.net 2.0中,加入了对这个高精度计时器的支持。不再需要P/Invoke,只需记住System.Diagnostics.Stopwatch。现在可以把上面的代码简化为:
  1. class TestClass
  2. {
  3.     static void Main(String[] args)
  4.     {
  5.         Stopwatch timer = new Stopwatch();
  6.         timer.Start();
  7.         //Do your test here
  8.         timer.Stop();
  9.         Console.WriteLine(timer.ElapsedMilliseconds.ToString());
  10.     }
  11. }

         简单多了不是吗。但这段程序还不够好,测试代码之前的代码可能产生了很多垃圾,而当你开始测试时,垃圾回收发生了,显然,这是不是我们所希望的。虽然我们不能控制GC精确的执行时间,但可以把GC对测试代码的影响减小到最低程度:
  1. class TestClass
  2. {
  3.     static void Main(String[] args)
  4.     {
  5.        Stopwatch timer = new Stopwatch();
  6.        // initialize your code here
  7.        
  8.        GC.Collect(2);
  9.        GC.WaitForPendingFinalizers();
  10.        GC.Collect(2);
  11.        GC.WaitForPendingFinalizers();
  12.         timer.Start();
  13.         //Do your test here
  14.         timer.Stop();
  15.         Console.WriteLine(timer.ElapsedMilliseconds.ToString());
  16.     }
  17. }

        在测试之前强制垃圾回收。WaitForPendingFinalizers()将会挂起当前线程,直到GC完全结束。注意,这里强制进行了2次垃圾回收。如果你对垃圾回收有所了解的话,那么应该知道当GC发现一个对象有Finalize()方法时,会先调用Finalize(),然后到下一次GC发生时才回收这个对象,我们确保在测试之前所有垃圾都已经回收释放了。

         好了,现在我们有了一个简单实用的测试模板,不过还有几点忠告是在测试时必须记住的 :
1. 在测试结束之前永远不要下结论
2. 在测试之前,至少执行一次测试代码。比如你的测试代码是Test(),那么在timer.start()前至少执行一次Test(),排除JIT对测试结果的影响。
3. 多运行几次程序,取平均值作为测试结果
4. 不要在Debug模式下执行测试
5. 不要在测试代码中输出测试信息,Console是相对较慢的操作。
6. 不同的CLR和编译器版本下的测试结果可能会不同。
以上忠告都来自好心的Tobias Hertkorm
         
         现在你已经成为性能分析大师了。不要再到论坛上问究竟是for还是foreach快这样的问题了,自己动手试试吧。当然,如果你比我还懒,那么下次来看我对for和foreach的分析结果吧 :)

  
  
 
【鸿蒙专题与实战】测试体系:单元测试、组件测试与 UI 测试 本文系统讲解鸿蒙开发中的三层测试实践:底层单元测试(用Hypium框架,优先覆盖纯函数、边界与异常)、中层ViewModel逻辑、顶层仅测3-5条关键UI路径。强调测试应“越往下写得越多”,因单元测试快且成本低,而UI测试慢易出错。通过实例说明断言拆分提升定位效率,结合覆盖率报告(hvigorwtest --coverage)发现盲区,核心是“用覆盖率找漏测,而非追求数字”。附五步落地清单:建测试文件、按优先级补用例、精简UI测试、生成报告、定位未覆盖行。下一篇将开启实战项目:从需求到上架全流程。 阅读详情

相关推荐

【VS2017】“LNK1104 cannot open file ‘python39_d.lib‘ “

记录一下编译调用了python代码的C语言源程序时遇到的问题 版本:以python3.9.1为例 先确保你安装了python的debug版本,如果没有,用对应版本安装包可以修改已经安装的python,如图。 选择 “Modify” 选择next 确保最后一项勾选,然后install。 光安装了还不够,需要配置一下C语言编译器。 以VS2017为例: 将python37_d.lib(在安装目录下的libs文件夹里有python39_d.lib)所在文件夹的路径添加到库目录里面,右键你的解决方案,选.

m0_46296905的博客 6474

使用VS对程序进行性能分析 -- 时间性能分析

  在算法实现或者程序设计过程中,往往会遇到运行时间过长,需要加速运行速度的情况,这个时候就需要对程序的时间性能进行分析,找出耗时最长的部分或者相对较长的冗余部分,下面将以 VS2003 为例进行说明。 1.使用 VS2013 进行性能分析   首先,如下图所示,点击 VS2013 上方的 “分析” --> “性能和诊断” 之后弹出如下的界面,选择 “性能向导” – > 点击 “开始...

dugudaibo的博客 2万+

从零搭建IoT数据中台:STM32+WebSocket实现边缘设备与Web端实时双向通信

本文详细介绍了如何从零搭建基于STM32和WebSocket协议的IoT数据中台,实现边缘设备与Web端的实时双向通信。通过硬件选型、协议设计、服务器搭建及安全优化,提供了一套低延迟、高并发的企业级解决方案,适用于智能农业和工业监控等场景。

tea88的博客 749

怎样测试程序的平均性能

标准库中的sort函数,是快速排序算法的典型实现。算法将含有n个元素的序列排序,平均需要 O(n log n) 时间。 上周,我提出了“测试一个程序的性能比测试其功能更难”这个观点。确认程序的性能达到标准以及确定“标准”的含义都十分困难。 接下来,我会继续讨论标准库中的sort(排序)函数。sort函数实现了快速排序算法,快速排序算法平均可以在 O(n log n) 时间内对含有n个元

u012388497的专栏 599

Windows 10错误代码解析与系统故障排除指南

操作系统错误代码是系统运行状态的直接反馈,Windows系统通过特定编码机制将故障信息转化为可识别的错误代码。从技术原理看,这些代码通常对应特定的异常处理流程,包括内存管理、驱动兼容性、文件系统等核心模块。理解错误代码对于系统维护具有重要价值,能快速定位问题根源,提高故障排除效率。在实际应用场景中,蓝屏错误(如0x0000007B)、系统升级失败(如0x80070002)和启动故障是最常见的三类问题。通过分析dump文件、使用WinDbg工具和系统内置诊断功能,可以有效解决大部分系统异常。特别是对于蓝屏错误

weixin_30516429的博客 298

qt工程引入opencv库步骤

第一步:新建qt工程 第二步:在工程名.pro文件中添加opencv库的路径                   INCLUDEPATH += /home/liyuanzhe/opencv-2.4.8/include/opencv \ /home/liyuanzhe/opencv-2.4.8/include/opencv2 LIBS += /home/liyuanzhe/open

superyuanzhe的专栏 5722

从零制作Arduino二进制时钟:硬件选型、电路设计与编程实战

实时时钟(RTC)是嵌入式系统中实现精准计时的核心模块,其原理是通过专用芯片和晶振提供独立于主控的稳定时间基准。在物联网和智能硬件项目中,RTC技术对于数据记录、定时任务和低功耗管理具有重要价值。本文以经典的DS1307 RTC模块与Arduino Uno结合为例,深入讲解如何构建一个二进制时钟系统。通过I2C通信协议读取时间数据,并利用位操作和LED驱动电路,将十进制时间直观地以二进制光点形式显示。该项目涵盖了微控制器编程、数字电路设计和硬件调试等嵌入式开发核心技能,为电子爱好者和初学者提供了一个完整的A

weixin_33698043的博客 673

夜间灯光遥感数据介绍及下载汇总

夜间灯光遥感数据介绍及下载汇总

qq_43874102的博客 1万+

AI学习-langgraph-2

是专门面向工具调用的运行时对象。工具函数中存在名为 runtime并且类型标注为 ToolRuntime的参数时底层运行时会在调用工具前自动注入 ToolRuntime实例。根据源码实现,某些不规范的写法也能注入运行时实例,但并不规范,不推荐。需要注意,ToolRuntime与图节点中使用的 langgraph.runtime.Runtime并不是同一个类型。前者额外提供了当前图状态、运行配置和工具调用 ID 等工具调用专属信息。当前版本,ToolRuntime@dataclass。

qq_62408075的博客 325

SAP CO-PA数据传送避坑指南:销售开票与FI/MM记账的日常配置实操(含KEKF/KE4I/KEI2)

本文深入解析SAP CO-PA数据传送中的常见配置问题,特别是销售开票与FI/MM记账环节的实操避坑指南。通过KEKF/KE4I/KEI2等关键配置点的详细说明,帮助用户避免数据失真和重复记录,提升获利能力分析的准确性。文章结合实战案例,揭示官方文档未提及的'数据黑洞'形成机制,为SAP顾问提供实用的排雷手册。

weixin_26905487的博客 390

水下机器人仿真平台选型指南:从AirSim到Unity3D的深度对比

本文深入对比了AirSim+UE和Unity3D两大水下机器人仿真平台的核心架构、传感器仿真能力和水下环境建模特点。AirSim+UE凭借高精度物理仿真和丰富传感器支持成为专业研发首选,而Unity3D则以快速开发和灵活扩展见长。文章为研发团队提供了全面的选型指南,帮助优化水下实验的仿真效率与成本。

weixin_29009669的博客 451

搬家了,新地址http://www.cnblogs.com/clayman/

   终于决定搬家,难用都还可以勉强忍受,可是最近居然开始乱封blog了,怕怕。可惜那么多文章带不走,手动把部份我觉得比较有价值的文章搬过去了。呵呵,欢迎大家有空过去看看:)。 此blog将不再更新...........

Clayman的专栏 18万+

GEE:基于自定义的年度时序数据集进行LandTrendr变化检测

本文介绍了使用年度时序数据进行LandTrendr变化检测的方法,包括核心函数调用、参数设置和结果可视化。通过筛选参数(年份、变化幅度和持续时间)对结果进行过滤,输出变化年份、变化幅度和持续时间。代码提供了完整的处理流程,包括数据输入、LandTrendr算法运行、结果筛选与可视化,并支持结果导出。适用于基于Google Earth Engine平台的地表变化检测分析。

养乐多的博客 752

0.033秒的艺术 --- Know How System.Math Works

0.033秒的艺术 --- Know How System.Math Works仅供个人学习使用,请勿转载,勿用于任何商业用途。       在对.net程序进行调试或者性能测试时,常常需要查看生成的IL代码,但仅仅有IL代码还是不够的,有时我们还希望查看CLR生成的最终asm代码。在VS里,可以非常方便的查看最终的asm代码:当程序执行到断点时,在代码窗口右键选择Go To

Clayman的专栏 5900

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

0.033秒的艺术 ---- XNA数学库中的陷阱

0.033秒的艺术 ---- XNA数学库中的陷阱仅供个人学习使用,请勿转载,勿用于任何商业用途。                上一次介绍了如何察看.net程序的asm代码,并且分析了System.Math下的部分函数。这一次,我们将更近一步,分析如何高效使用XNA中的数学的库。下文仅以Matrix和Vector3为例,其余类型均可依此类推。为了达到测试和演示的目的,我写了一段相当”

Clayman的专栏 4367

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

0.033秒的艺术 --- 二叉树遍历

0.033秒的艺术 --- 二叉树遍历仅供个人学习使用,请勿转载,勿用于任何商业用途。        最近在写一些关于树的操作,显然最常见的树操作就是遍历所有节点,而遍历节点,最常见的算法自然是递归。下面是最初的二叉树实现和遍历public class Node{ public Node left; public Node right; publi

Clayman的专栏 3796

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

0.033秒的艺术 --- for vs. foreach

0.033秒的艺术 --- for vs. foreach仅供个人学习使用,请勿转载,勿用于任何商业用途。        一直以来,关于C#中for和foreach孰优孰劣的争论似乎从来就没有停止过,各种谣言和真相混杂在一起,以至于这似乎变成了一个很复杂的问题。For的fans认为,foreach内部会分配enumerator,产生垃圾,影响性能;而foreach的支持者则认为编译器会对f

Clayman的专栏 1569

从瀑布到流水线:DevOps 入门与 GitLab + Jenkins + Docker 落地实践

先看清软件开发生命周期(SDLC)的全貌,再对比瀑布模型与敏捷开发,随后进入持续集成与 CI/CD 的机制内核;最后落到实操——在 GitLab、Jenkins、Docker 组成的四机实验环境里,走完源码托管、自动化构建、镜像封装与远程部署,直到参数化构建与版本回滚。概念与命令并重,既是入门地图,也是操作手册。

年轻的时候很穷,经过我多年的努力,终于不再年轻。 244

训练数据示例

针对“规格书生成测试用例脚本”的任务,在 LLaMA-Factory 中使用即可。关键是把“规格书内容”放进input字段,把“期望的脚本输出”放进output字段。

liuxs2009的专栏 57

DNS 不是把域名翻译成 IP:递归解析、TTL 缓存、CNAME 与报文排错实战

本文通过离线Python实验,拆解DNS递归解析、缓存机制与报文结构,揭示“DNS不是全局映射表”的本质。重点解析递归器角色、TTL衰减、CNAME链处理、负缓存隔离及修改记录延迟生效等核心问题,结合实战排错案例,阐明缓存层级、事务匹配、截断处理与安全边界,强调从应用到权威的逐层排查逻辑,实现可复现、可验证的DNS教学系统。

此人很懒,什么都没有写~~ 348

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

Java EE 进阶:8.MyBatis 操作数据库(入门)(第一弹)

要努力去发光,而不是被照亮~ 123

【LTE L3 笔记 09】LTE物理信道-PRACH

课程来源:B站《【2022】华为HCIA-LTE无线工程师认证学习中级视频》笔记为个人整理,含课件截图,仅供学习交流。

lyouhuan的博客 188

密码存储不是 MD5 加盐:PBKDF2、scrypt、参数升级与安全验证实战

本文通过实战演示密码存储的正确做法:摒弃MD5加盐,采用PBKDF2与scrypt等高成本密钥派生函数,结合随机盐、版本化记录与严格解析,确保离线破解成本可控。模块实现安全验证、参数校验、透明升级与统一错误处理,强调算法选择需兼顾安全性与可维护性,提供教学级密码存储方案,助力构建可迁移、可审计的认证边界。

此人很懒,什么都没有写~~ 227

软件测试用例模板怎么写:从用例设计到执行记录的全套指南

测试用例是测试工作的核心产出,它决定测试覆盖了多少、漏掉了什么。但大多数人的测试用例写得像流水账——只有正常路径,没有异常场景;只有操作步骤,没有预期结果;只有功能测试,没有非功能测试。本文拆解测试用例的标准结构,说明每个字段的含义和写法,给出覆盖功能测试、性能测试、安全测试的完整用例范例,并列出测试用例设计的五个高频遗漏点。

wuwangzhiduoshao的博客 149
上一篇: XNA下的中文显示
下一篇: Font System Finished!
soilwork
博客等级 码龄23年 290粉丝 116原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值