Code

2015年2月10日火曜日

AngularJS パフォーマンスは良くない?ー>いいえ、使い方次第です。

 アップデート 2016/05/01:AngularJS 1.0 に比べて、React.js のほうが良いです。AngularJS の bi-direction binding、ng-repeat などは使い易いですが、DOM 操作が多くて、重いです。React.js も同じ機能が簡単に作れます。さらに、AngularJS 1.0 の Learning Curve が高いから、習うにはなかなか時間がかかります。React.js を使うと、どんどん Component が作れて、ますます開発効率が上がります。

 追加 2016/03/07:最近、React.js を使うたびに、AngularJS は難しいなと感じ始めています。1.0 では概念が多くてなかなか使いにくいですね。React.js の場合、概念も簡単だし、Flux を使うと、アプリの構造はかなり簡単になります。また速いです。まぁ、速くするためには、shouldComponentUpdate 関数を細かく実装すればいいので、はっきりしています。今後続けて React.js を使おうと思います。新規プロジェクトの場合、AngularJS 2.0 を待ったほうがいいです。でも、古いバージョンのブラウザをサポートするためには、React.js のうほうがよさそうです。時間があれば、また http://aurelia.io/ を見てみようかと。Polymer はどうやら、遅いようなきがしています。。。後日、ちゃんと勉強してみよう。

 最近、隣のグループは react.js に転向したので、再び AngularJS のパフォーマンス問題が提起されました。実際はどうですかね。。。
 まぁ、個人的な感じでは、JavaScript 根本的にパフォーマンスが良くないです。AngularJS は良く重いと言われてます。特に Dirty Check の実行サイクルが考えば考えるほど重いと思われています。でも、どんなフレームワークでも、react.js、ember.js でも、そういう長いループが存在しています。だから、Dirty Check はそんなに大きいな問題でもないと思います。
 問題は利用者側にあると思います。なぜなら、たぶん結構な数の開発者は $timeout や, $http の中に $rootscope.$apply 関数が呼ばれてると知らないです。それで、無意味に $timeout を呼んだり、自分でその中に $apply を使ったりしています。そうすると、AngularJS は2回 Dirty Check をやるので、重いですね。
 つまり、フレームワークとして、AngularJS はあまり複雑で、なかなか全部理解するには時間がかかります。そのあと、チューニングとかもしないから、問題を発見して、解決するプロセスが欠けてます。
 じゃ、どうしたら AngularJS のパフォーマンスが向上できますかね?
 まず、$apply 関数を理解しましょう。$apply 関数は $digest 関数を読んで、もしエラーとか、Exception が発生したら、ちゃんとエラースタックをリストできます。(中に try-catch があるので)。$digest  は登録した expression を実行して、過去の値と現在の値を比較して、変更があったら、変更の Handler 関数を呼びます。Handler 関数の中にもし何か値変更があったら、また $digest が実行されます、変更がないまで、実行し続けます。それで、$digest が10回まで繰り返し呼ばれます。10回以上の場合、Exception が Throw されます。
 それで、もし登録した expression の数が最小限に抑えるなら、そのサイクルが短くなります。AngularJS 1.3 から {{::express}} が導入されました。もし expression が最初の一回のみ値を設定する必要があるなら、:: で一回のみ binding されます。これも bind-once という関数があります。また bindonce という別のライブラリもあります。
 あと、すべての HTML 要素を ng-app 範囲にする必要がないので、例えば ng-non-bindable を使ったりして、directive の parse 範囲を小さくすることができます。以前も書いたように、jQuery UI を使うと、かなりの量の HTML 要素が作られます。それを parse するあまり必要ないし、"IE FIX" コメントも追加されますので、たまに Widget を壊します。だから、必要のない部分はもう non-bind して、apply directive 過程を止めます。
 次、1ページはすべて AngularJS の ng-app 範囲にすると、かなりの expression 量が増えますので、controller を親子にしないで、独立のスコープなら、もうそのスコープの $digest 関数を呼ぶとか、Dirty Check の量を減らせます。
 
 まぁ、よほど大きい web app じゃない限り、AngularJS のパフォーマンスは悪いと言えないと思います。すべて使い方次第ですね。
 どんなフレームワークを使うと、必ず overhead が発生しますので、良くデザインして、必要な部分と必要ない部分をちゃんと分けて、パフォーマンスは良くなります。

 #余談ですが、jQuery のパフォーマンスはかなり悪いです。通常の Vanilla JS を使うと、同じ関数が jsperf.com でテストすると、なん百倍の差が出ます。なぜなら、ライブラリだから、エラーチェックや、browser の違いを綺麗にカバしたいからです。以前 iOS の WebView も jQuery を使うと重く感じましたので、jQuery Lite を作って、パフォーマンス向上できました。使い方次第ですね。

0 件のコメント:

コメントを投稿