如何在Angular中测试渲染速度

Emp*_*nal 9 javascript performance performance-testing angularjs

我们正在构建一个Angular应用程序,我们正试图弄清楚如何获得渲染各种页面需要多长时间的基准.我在performance.timing 这里读过,但这似乎只适用于非单页面应用程序,因为当我在应用程序中导航到新视图时,时序数字不会改变.

理想情况下,我们可以插入一些代码来获取各种视图的渲染时间,并将它们发布到我们的Big Query服务中.

关于如何在Angular应用程序中获取视图的时序信息的任何想法?

编辑:

更具体地说,您将转到加载大型重复列表的路径(这对于性能而言不是最佳的),并且窗口在实际呈现列表中的项之前有很长的延迟.我们想看看从大空白视图到渲染列表中的项目需要多长时间.

Ale*_*lor 12

TypeScript / Angular (2+) 答案:

要对 Angular 渲染组件树所花费的时间进行基准测试,请在更改检测之前和之后进行测量。这将计算 Angular 创建所有子组件并评估ngIfs / 所需的时间ngFor s 等所需的时间。

有时,当更改检测运行时,什么都不会改变,时间间隔会很小。只需寻找最长的时间间隔,这可能就是所有工作发生的地方。此外,最好为此使用 OnPush 更改检测策略。见http://blog.angular-university.io/onpush-change-detection-how-it-works/

在你的上面声明这个 Timer 实用程序@Component({...}) class

class Timer {
  readonly start = performance.now();

  constructor(private readonly name: string) {}

  stop() {
    const time = performance.now() - this.start;
    console.log('Timer:', this.name, 'finished in', Math.round(time), 'ms');
  }
}
Run Code Online (Sandbox Code Playgroud)

你的组件类中添加这个:

private t: Timer;

// When change detection begins
ngDoCheck() {
  this.t = new Timer('component 1 render');
}

// When change detection has finished:
// child components created, all *ngIfs evaluated
ngAfterViewChecked() {
  this.t.stop();  // Prints the time elapsed to the JS console.
}
Run Code Online (Sandbox Code Playgroud)

请注意,Angular 渲染与屏幕上的浏览器渲染(绘制)是分开的。这也需要时间。当您在 Chrome 时间线工具(javascript 开发人员控制台 -> 性能 -> 记录)中看到带有大量“checkAndUpdateView”和“callViewAction”调用的 javascript(黄色)时,即发生了 Angular 渲染。当您在 Chrome 时间线工具中看到标有“渲染”的紫色时,这就是实际的浏览器渲染。


Emp*_*nal 8

在做了一些实验之后,我找到了一种方法来估计视图渲染的时间长度.

场景:

  1. 路由到Angular应用程序中的页面
  2. 进行AJAX调用以获取冗长的项目列表
  3. 拿出物品清单,进入一个 ng-repeat ul
  4. 查看呈现的列表

在Angular应用程序中,ng-repeat是一个臭名昭着的性能杀手,但它非常方便.下面是关于性能的讨论,并在这里.

假设我们希望得到从#3到#4所需时间的近似值,因为测试AJAX调用性能非常简单.

这是一些背景:

<ul>
  <li ng-repeat="item in items">
    {{item.name}}
    <!-- More content here -->
  </li>
</ul>
Run Code Online (Sandbox Code Playgroud)

在Angular控制器内部:

// Get items to populate ng-repeater
MyApiService.getItems(query)
  .then( function (data) {
    $scope.items = data;
    // When callback finishes, Angular will process items
    // and prepare to load into DOM
  }, function (reason) {
    console.log(reason);
  });
Run Code Online (Sandbox Code Playgroud)

通过@runTarm,提到的事件$routeChangeStart,$routeChangeSuccess以及$viewContentLoaded一旦路径被加载火,但DOM渲染项目之前,所以他们不解决问题.但是,通过实验,我发现一旦AJAX回调完成并设置$scope.items,Angular就会开始处理items和准备ng-repeat ul插入DOM 的阻塞操作.因此,如果您在AJAX调用完成后得到时间,并setTimeout在回调中指定的时间内再次获得时间,则setTimeout回调将排队等待Angular完成转发器进程并让您在时间段前一瞬间获得时间. DOM渲染,为您提供最接近渲染时间的近似值.它不是实际的渲染时间,但对我们来说缓慢的部分不是DOM正在做它的工作,而是Angular,这是我们想要测量的.

这是修改后的例子:

// Get items to populate ng-repeater
MyApiService.getItems(query)
  .then( function (data) {
    var start = new Date();
    $scope.items = data;
    // When callback finishes, Angular will process items
    // and prepare to load into DOM
    setTimeout( function () {
      // Logs when Angular is done processing repeater
      console.log('Process time: ' + (new Date() - start));
    }); // Leave timeout empty to fire on next tick
  }, function (reason) {
    console.log(reason);
  });
Run Code Online (Sandbox Code Playgroud)

  • 除了自己录制时间外,您可能会发现Chrome Devtools的Flame图表功能非常有用!https://developer.chrome.com/devtools/docs/cpu-profiling (4认同)