【问题标题】:AngularJS: Determining how much time the directive takes to renderAngularJS:确定指令渲染所需的时间
【发布时间】:2017-02-04 07:35:26
【问题描述】:

我如何测量一个指令(元素)需要多少渲染? 如果不是,是否可以确定哪个指令花费最多的时间来呈现?

PS. 是的,我使用了Batarang,但它只显示了耗时最长的手表表达式。是的,我用谷歌搜索并找到了一个非常相似的question,但那里仍然没有答案。

【问题讨论】:

  • 总有this
  • 你想解决什么更高层次的问题?
  • @charlietfl,我遇到了性能问题,并试图了解是什么指令导致它们

标签: javascript angularjs


【解决方案1】:

对于没有任何 Promise 的指令,我们可以使用另一个指令 $compile 它的元素,然后在 $compile 的回调函数中调用 $timeout 而不进行脏检查(第三个参数 - 假):

app.directive('measure', function () {
  return {
    controller: function ($scope, $element, $compile, $timeout, $window) {
      $window.start = new Date().getTime();
      // make sure to compile only once
      if (!$window.done) {
        console.log('STARTING MEASUREMENT');
        $window.done = true;
        $compile($element)($scope, function(clonedElement, scope) {
          var timer = $timeout(function () {
            console.log('ENDING MEASUREMENT: ' + (new Date().getTime() - $window.start) + 'ms');
            $timeout.cancel(timer);
          }, 0, false);
        });
      }
    }
  };
})

对于带有 Promise 的指令,我们可以再次使用 $timeout 来测量它,而无需脏检查,而是在最后一个 Promise 的 then 块中调用:

app.directive('someOtherDir', function () {
  return {
    template: '<div ng-repeat="item in vm.data"><img ng-src="{{ item.thumbnailUrl }}" title="{{ item.title }}"></div>',
    controller: function ($http, $timeout, $window) {
      console.log('STARTING MEASUREMENT');
      $window.start = new Date().getTime();
      var vm = this;
      $http.get('data.json').then(function (res) {
        vm.data = res.data;
        var timer = $timeout(function () {
          console.log('ENDING MEASUREMENT: ' + (new Date().getTime() - $window.start) + 'ms');
          $timeout.cancel(timer);
        }, 0, false);
      });
    },
    controllerAs: 'vm'
  };
});

这是我的playground plunkerhttp://plnkr.co/edit/McWOeF7rZ7ZYKnDWafy6?p=preview,注释/取消注释2个指令,尝试在someDir指令中增加i

for (var i = 0; i < 20; i++) {
  vm.dates.push({
    timestamp: i * 1000 * 60 * 60 * 24,
    label: new Date(i * 1000 * 60 * 60 * 24).toString()
  });
}

尝试 200、2000...

【讨论】:

    【解决方案2】:

    老实说,这个问题本身并没有很好的答案,我将在下面详细解释。这个问题,至少在我看来,更像是达到目的的一种手段。所以我认为我们需要找到真正问题的核心:


    您是否遇到了您正在尝试识别的性能问题,或者您只是在尝试分析以证明某些东西足够快?


    不幸的是,要知道一个指令需要多长时间来渲染,变量太多了,例如:

    • 子指令
    • 异步模板加载
    • 布局抖动

    仅举几个重要的击球手。此外,所有指令都会添加元素或设置一些类,然后控制浏览器本身以呈现布局。一旦控制权被移交,你基本上就不走运了。

    修改 DOM 快,非常快,拿Velosity.js 证明 JS 可以产生比 CSS 更快更窒息的动画,但是有限制:

    • 限制 DOM 元素的数量,不要向用户显示数千行中的 10 行。
    • 修改元素类的样式列表,由于 CSS 级联,意味着所有子元素都会重新呈现。在正文中添加了一个类?您的整个页面只是为了再次渲染。
    • 写入 DOM 然后从 DOM 读取属性会强制页面立即确保布局正确,从而强制渲染。快速执行多次操作会导致布局抖动(DOM 的多次顺序强制渲染)。

    【讨论】:

      【解决方案3】:

      为什么不直接使用 Chrome 的时间线检查器?

      您可以在渲染之前开始记录时间线,然后在状态更改后结束。

      单独渲染指令的时间线将是紫色的时间,紫色和绘画楔形的总和将为您提供从 XHR 提取完成到模板被绘制到屏幕上的总时间。这有什么不准确的原因吗?

      【讨论】:

        【解决方案4】:

        我建议以下变体

        myApp.directive('log', function() {
        
            return {
                controller: function( $scope, $element, $attrs, $transclude ) {
                    console.log( Date.now() + ' (dirrective controller)' );
        
                    //some stuff here
                },
                link: function( scope, element, attributes, controller, transcludeFn ) {
                     //some stuff here
        
                     console.log( Date.now() + ' (dirrective post-link function)' );
                 }
             };  
        
        });
        

        第二个日志和第一个日志之间的差异与渲染指令所花费的时间非常相似。

        【讨论】:

        【解决方案5】:

        我创建了指令来检查角度视图的渲染时间。指令使用简单但有用的 speeder 库 - https://github.com/maciejsikora/Speeder。它计算从ms-start 渲染到ms-stop 渲染的微秒。

        <span ms-perf ms-start='symbol'></span>
        
        ...here some actions ng-ifs, repeats etc.
        
        <span ms-perf ms-stop='symbol'></span>
        

        使用带有 ng-repeats 的指令的完整示例: https://jsfiddle.net/maciejsikora/4ud2rLgz/

        示例指令在控制器中使用,但它也可以在另一个指令中使用。该解决方案的缺点是我们需要将指令附加到 DOM 并在发现问题后将其从那里删除。当然,好主意是创建提供程序并对其进行配置以用于开发和生产环境,因此在生产中不应运行任何结果和时间计数。

        【讨论】:

          猜你喜欢
          • 2016-12-23
          • 1970-01-01
          • 2016-05-22
          • 1970-01-01
          • 2013-06-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多