Quantcast
Channel: 黑暗執行緒
Viewing all articles
Browse latest Browse all 2311

KendoGrid+Angular顯示大量資料的效能問題

$
0
0

接獲使用者反應,某個使用KendoGrid顯示大量資料的網頁,用IE檢視的話速度慢到嚇人。聞此言,馬上打開IE11測試,果真嚇得我差點閃了兩滴… 也太慢了吧!

先交代問題情境,專案使用Angular搭配Kendo UI開發,順理成章使用Kendo UI提供的Angular Directive,寫成<div kendo-grid …>,資料筆數偏多,大約一千多到兩千筆,基於KendoGri的強大彈性及高複雜度,處理起來多耗點時間倒也合理,但這個案例在IE的表現與期望出入頗大,值得調查。

修改KendoGrid的官方範例,我設計了一個實驗:

<divid="example"ng-app="KendoDemos">
<divng-controller="MyCtrl">
<buttonng-click="loadData()">Load Data</button>
<spanng-bind="duration"></span>
<divkendo-grid="grid"options="mainGridOptions">
</div>
 
</div>
</div>
<script>
    angular.module("KendoDemos", [ "kendo.directives" ])
        .controller("MyCtrl", function($scope){
var data = [];
for (var i = 0; i < 2000; i++) {
              data.push({
                FirstName: "FN" + i,
                LastName: "LN" + i,
                Country: "CN" + i,
                City: "CT" + i,
                Title: "T" + i
              });
            }
            $scope.loadData = function () {
                st = new Date();
                $scope.grid.dataSource.data(data);
            };
var st;
            $scope.mainGridOptions = {
                dataSource: [],
                height: 600,
                sortable: true,
                pageable: false,
                columns: [
                    { field: "FirstName", title: "First Name", width: "120px" },
                    { field: "LastName", title: "Last Name", width: "120px" },
                    { field: "Country", width: "120px" },
                    { field: "City", width: "120px" },
                    { field: "Title" }
                ],
                dataBound: function () {
if (st) {
                        setTimeout(function () {
                            $scope.duration = new Date() - st + "ms";
                            $scope.$digest();
                        }, 1);
                    }
                }
            };
        })
</script>

網頁使用Directive建立KendoGrid,按鈕後將2000筆資料放入KendoGrid中,重點按鈕到資料顯示完成所需的時間(dataBound事件將在整個Grid的DOM生成後觸發),實測IE11耗時3秒。透過F12開發者工具的分析工具,抓出速度慢的源頭在Angular的compile、publicLinkFn等方法,共執行1979次,耗費2秒以上。

此一發現讓人合理推測如果不用Angular Directive,改以純jQuery方式建立KendoGrid,效率應會提升。所以我又寫了對照組:

<divid="example">
<div>
<button>Load Data</button>
<spanid="duration"></span>
<divid="grid">
</div>
 
</div>
</div>
<script>
var data = [];
for (var i = 0; i < 2000; i++) {
            data.push({
                FirstName: "FN" + i,
                LastName: "LN" + i,
                Country: "CN" + i,
                City: "CT" + i,
                Title: "T" + i
            });
        }
var st, ed;
        $("#grid").kendoGrid({
            dataSource: [],
            height: 600,
            sortable: true,
            pageable: false,
            columns: [
                { field: "FirstName", title: "First Name", width: "120px" },
                { field: "LastName", title: "Last Name", width: "120px" },
                { field: "Country", width: "120px" },
                { field: "City", width: "120px" },
                { field: "Title" }
            ],
            dataBound: function () {
if (st) $("#duration").text(new Date() - st + "ms");
            }
        });
        $("button").click(function () {
            st = new Date();
            $("#grid").data("kendoGrid").dataSource.data(data);
        });
</script>

幾乎相同的程式邏輯,差別在改用jQuery建立KendoGrid及處理按鈕事件,實測速度可縮短至1.2秒,證明速度慢確實與啟用Angular有關。使用分析工具觀察,同樣的欄位設定,不使用Angular時,KendoGrid在_renderContent()經由指定innerHTML產生畫面元素,省去Angular模式的comple、建立scope、產生dataItem物件環節,邏輯相對單純,應是耗費時間變少的主因。

不過,這種模式不能在欄位Template使用<span ng-bind="dataItem.propName">等Angular寫法,無法叫用現成的Directive、Filter等,不利邏輯集中與程式碼共用。有利有弊,實務應用時就必須做出取捨,而二者的效能差距數字是判斷的關鍵。

寫了兩個測試網頁放在JSBin:KendoGrid + Angular版 vs KendoGrid + 純jQuery,用IE11、Edge、Chrome及Firefox做了不專業的測試。操作方法是重新載入網頁,按下Load Data鈕,反覆數次取最低值,測試結果為:

  • IE11:2.3秒 vs 0.8秒
  • Edge:2.2秒 vs 0.8秒
  • Chrome:1.1秒 vs 0.3秒
  • Firefox:1.1秒 vs 0.3秒

由於沒有精準地控制環境、變因,以上數據並不具權威性,但足以確定啟用Angular時速度慢了約三倍,在資料量小的情境差別有限,若遇到上千筆資料時,就有可能讓使用者皺眉。而這個問題在IE上又格外嚴重,在面對類似情境時要特別留意,甚至放棄Angular Template回歸純jQuery模式改善效能。

留下兩點值得探討:

  1. 原本預期Edge的效能應逼近Chrom,但實測卻跟IE11近乎相同,有一種可能是KendoGrid的程式有針對不同瀏覽器優化,Edge未受惠,或是我的測試環境有問題,歡迎使用Windows 10的朋友幫忙複測看看。
  2. 直覺KendoGrid使用Angular架構產生資料列所遇到的效能議題,在巨量ng-repeat或網頁內含大量採用Template生成DOM的Directive時也將面臨相同挑戰,這點留待日後驗證。

Viewing all articles
Browse latest Browse all 2311

Trending Articles