本站已关停,现有内容仅作科研等非赢利用途使用。特此声明。
查看: 2906|回复: 0
打印 上一主题 下一主题

Dart 性能测试

[复制链接]
跳转到指定楼层
1#
发表于 2013-3-1 20:56:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 hanguokai 于 2013-4-2 22:58 编辑

原文:http://han.guokai.blog.163.com/b ... 182712013215637623/

我们通常需要对代码或核心算法做性能测试。性能测试的概念非常简单:执行要测试的代码,测量其执行时间(一般是多次测试的平均值)。性能测试真正的难点是避开各种干扰因素,而这些干扰因素可能非常复杂。除了自身代码,还可能涉及硬件、底层系统、语言、库的实现等各个方面。Dart 中的性能测试和其它语言并没有什么不同,只不过需要注意几点。

1. 热身
Dart 语言的一个目标是快速启动,为此 Dart VM 并不会立刻优化要执行的代码。执行时间太短、次数太少的代码无法触发 VM 的优化器,这样的结果并不能反映真实的性能数据。所以,在正式开始记录执行时间之前要预先执行足够多的次数和时间,然后再开始测试性能。

除了热身,测试本身也要执行足够的时间和次数才能获得准确的数据,尤其是单次执行时间很短的测试。

2. 关闭检查模式和调试模式
Dart 有两种执行模式:检查模式(checked)和生产模式(production)。检查模式会在运行时插入大量类型检查,自然会影响性能。命令行模式下 dart 默认就是生产模式。但在 Dart Editor 中默认是在检查模式下运行,首先保证程序在检查模式下执行没问题,然后在性能测试时在程序的启动配置中取消 VM 的 “Run in checked mode”选项。

此外,debug 模式也会对性能有影响。在 Dart Editor 的选项配置中,Run and Debug 中的 break on exceptions 设为 none 。

基本性能测试代码
假设要执行的测试函数为 func() ,那么代码大概是像下面这样:
  1.   int m = 10, n = 100;
  2.   //预先执行 m 次调用作为热身,但不计时间
  3.   for(int i = 0; i < m; i++){
  4.     func();
  5.   }
  6.   
  7.   //开始计时,并执行 n 次调用
  8.   var st = new Stopwatch()..start();
  9.   
  10.   for(int i = 0; i < n; i++){
  11.     func();
  12.   }
  13.   
  14.   //打印测试结果
  15.   print("Runtime is ${sw.elapsedMicroseconds/n} us");
复制代码
在 Dart 中 Stopwatch 用于计时,Stopwatch 对象有两个属性表示启动之后逝去的时间:elapsedMilliseconds(逝去的毫秒) 和 elapsedMicroseconds(逝去的微妙,即千分之一毫秒)。以上代码用的是微妙,也可以用毫秒。


对应的 JavaScript 代码是:
  1.   var m = 10, n = 100;
  2.   for(var i = 0; i < m; i++){
  3.     func();
  4.   }
  5.   
  6.   var start = (new Date).getTime();

  7.   for(var i = 0; i < n; i++){
  8.     func();
  9.   }
  10.    
  11.   var time  = ((new Date).getTime() - start)/n;
复制代码
这里 (new Date).getTime() 获得的时间单位是毫秒。


为了保证代码被执行足够的时间(比如1s以上),需要适当调整 m 和 n 的值。还有一个更通用的方法可以保证代码至少执行给定的时间:
  1. double measureFor(Function f, int timeMinimum) {
  2.   int time = 0;
  3.   int iter = 0;
  4.   Stopwatch watch = new Stopwatch();
  5.   watch.start();
  6.   int elapsed = 0;
  7.   while (elapsed < timeMinimum) {
  8.     f();
  9.     elapsed = watch.elapsedMilliseconds;
  10.     iter++;
  11.   }
  12.   return 1000.0 * elapsed / iter;
  13. }
复制代码
上面这个函数摘自 benchmark_harness 库,f 是要执行的测试,timeMinimum 是执行的最少时间(毫秒),返回每次执行的微秒。


利用 benchmark_harness 进行测试
Dart 提供了 benchmark_harness 库用于性能测试,这个库的实现非常简单,就是在干我们前面说的那些事。

在 pubspec.yaml 中添加:
  1. dependencies:
  2.   benchmark_harness: any
复制代码
执行 pub install,然后导入:

  1. import 'package:benchmark_harness/benchmark_harness.dart';
复制代码
使用时可以 copy 提供的代码模版,其中 run 是要执行的测试:

  1. // Import BenchmarkBase class.
  2. import 'package:benchmark_harness/benchmark_harness.dart';

  3. // Create a new benchmark by extending BenchmarkBase
  4. class TemplateBenchmark extends BenchmarkBase {
  5.   const TemplateBenchmark() : super("Template");

  6.   static void main() {
  7.     new TemplateBenchmark().report();
  8.   }

  9.   // The benchmark code.
  10.   void run() {
  11.   }

  12.   // Not measured setup code executed prior to the benchmark runs.
  13.   void setup() { }

  14.   // Not measures teardown code executed after the benchark runs.
  15.   void teardown() { }
  16. }

  17. main() {
  18.   // Run TemplateBenchmark
  19.   TemplateBenchmark.main();
  20. }
复制代码
这里继承了 BenchmarkBase ,然后覆盖 run 方法,最后调用 report 方法执行。

注意输出的结果是以10次测试为单位的平均值(而非一次测试的结果)。


参考资料:


ChinaGDG.com
回复

使用道具 举报

*滑动验证:
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表