[angularjs] jquery vs angularjs vs angular 2.0顯示大量資料效能比較

[angularjs] jquery vs angularjs vs angular 2.0產生大量資料效能比較

前言

 

這篇其實是看到了黑大這篇Angular顯示大量物件效能測試,針對三種方式的效能比較,加上我對angular 2.0的效能好奇有多大的進步,所以實際寫了程式碼,來做個比較,在黑大的文章裡面,是使用alert把實際跑的毫秒顯示出來,在此我使用console.time的方式來顯示。

 

原始碼部份

 

如果以黑大的那篇比較來看,html直接產生dom的方式是最快的,但後來我想要實測更大的數據量來比較,結果發現案情似乎並不單純,如果以chrome來說,先組完html再直接用html印出來反而是最慢的,以下是我測試的程式碼,我把四種方式都寫在同樣的頁面裡面,如果有開始在study angular 2.0的人,可以自己把程式碼複製回去,實測玩看看。

 

index.html


<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title></title>
    <script src="https://kendo.cdn.telerik.com/2015.3.930/js/jquery.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.js"></script>
    <script src="../node_modules/systemjs/dist/system.src.js"></script>
    <script src="../node_modules/angular2/bundles/angular2.dev.js"></script>
    <script type="text/javascript"></script>
    <script>
    System.config({
        packages: {
            'app': {
                defaultExtension: 'js'
            }
        }
    });
    System.import('app/app');
    </script>
</head>

<body>
    <div id="example" ng-app="KendoDemos">
        <div ng-controller="MyCtrl">
            <button ng-click="loadData()">Load Data(NG)</button>
            <button id="btnLoadDataHtml">Load Data(jQuery html)</button>
            <button id="btnLoadDataDOM">Load Data(jQuery DOM)</button>
            <div class="list">
                <span ng-repeat="item in items">

                    {{item.FirstName}} {{item.LastName}}

                    {{$parent.calcDura($last)}}

                </span>
            </div>
        </div>
    </div>
    <app>Loading...</app>
    <script>
    var data = [];

    for (var i = 0; i < 20000; i++) {

        data.push({

            FirstName: "FN" + i,

            LastName: "LN" + i,

            Country: "CN" + i,

            City: "CT" + i,

            Title: "T" + i

        });

    }

    angular.module("KendoDemos", [])

    .controller("MyCtrl", function($scope) {

        $scope.calcDura = function(last) {

            if(last){
                console.timeEnd('angular');
            }
        };

        $scope.loadData = function() {
            console.time('angular');
            st = new Date();
           
            $scope.items = data;
        };

    });

    $("#btnLoadDataHtml").click(function() {
        console.time('jquery html');
        var st = new Date();

        var h = $.map(data, function(item, i) {

            return "<span>" + item.FirstName + " " + item.LastName + "</span>";

        }).join("\n");
        var $list=$(".list").html(h);
        console.timeEnd('jquery html');
        //alert((new Date() - st) + "ms");
        
    });

    $("#btnLoadDataDOM").click(function() {
        console.time('jquery attr');
        var st = new Date();

        var $list = $(".list");

        $.each(data, function(i, item) {

            $("<span>" + item.FirstName + " " + item.LastName + "</span>").appendTo($list);

        });

        console.timeEnd('jquery attr');

    });
    </script>
</body>

</html>

 

angular 2.0的app.ts部份


import {Component, bootstrap,CORE_DIRECTIVES} from 'angular2/angular2';

@Component({
    directives:[CORE_DIRECTIVES],
    selector:'app',
    template:`
    <button type="button" (click)="loadDate()">angular2</button>
    <span *ng-for="#hero of heroes; #i=last">
        {{ hero.FirstName }}-{{hero.LastName}}-{{hero.Country}}-{{hero.City}}-{{hero.Title}}
        {{calcDura(i)}}
    </span>
    `
})

class AppComponent{
    data: PeopleModel[];
    heroes: PeopleModel[];
    constructor(){
        this.data = new Array<PeopleModel>();
        for (var i = 0; i < 20000; i++) {
            this.data.push({
                FirstName: "FN" + i,
                LastName: "LN" + i,
                Country: "CN" + i,
                City: "CT" + i,
                Title: "T" + i
            });
        }
    }
    calcDura (last){
        if (last) {
            console.timeEnd('angular2');
        }
    }

    loadDate(){
        console.time('angular2');
        this.heroes = this.data;
    }
}

class PeopleModel{
    FirstName: string;
    LastName: string;
    Country: string;
    City: string;
    Title: string;
}

bootstrap(AppComponent);

 

效能比較

 

在此我先以20000筆來實測,在此我只要測試完一個,就會把頁面重整,這樣比較能清楚看出畫面和最後log出來的秒數,順序為angularjs->jquery組好html再塞給dom->jquery用attr的方式加到dom裡面,->angular 2.0

 

test

 

第一個例子是用chrome做測試,從上面的圖示可以看出來,jQuery html的秒數先跑完了,但畫面還等蠻久的才出來,實際上第二個案例只是javascript跑完的時間,並不是最後面畫面呈現完的時間,結果反而是先在jquery組裝完,然後直接印在html裡面反而是最慢的,以四個例子來比較最快的是angular 2.0>jquery attrs>angularjs>jquery html

 

第二個例子我用firefox來測試,速度來說反而是jquery html>angular 2.0>jquery attrs>angularjs,而且很明顯的firefox的log時間也確實是跟著畫面一起呈現的,edge的話也是jquery html方式最快,angular 2.0還跑得出來,jquery attrs和angularjs死當,所以我只好放棄,下面則是firefox實際的效果。

 

test1

 

結論

 

edge因為實測過程一直死當,只能放棄測試,然後如果重覆產生的話,angularjs和angular 2.0應該是有做快取機制,幾乎都是5ms以內跑完,jquery則是每次都需要那麼久的時間,總結一下;對我來說angularjs是一個能很快速就開發一個spa的框架,但只要應用越來越大的時候,這種弱型別還有效能確實還是有缺陷在,angular 2.0則是寫法邏嗦點,但是為了可讀性跟後續維護,還有大型應用的效能考量點,則能提供很大的幫助,雖然很多人會覺得angular 2.0跟angularjs幾乎是兩個不一樣的框架,但其實我個人認為在angularjs的設計觀念上,angular 2.0在很多地方還是很相似的,雖然angularjs也可以用typescript來寫,但如果真的需要用到強型別的概念來開發,我個人會傾向於直接使用angular 2.0來開發,畢竟連官方文章的範例都是直接以typescript了,以上再請各位多多指教和批評。