Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Improve SPA Performance with Angular App

mana
June 21, 2017

Improve SPA Performance with Angular App

Tips on improving performance of SPA using Angular.
- JavaScript memory leak
- AngularJS / Angular2 performance
- New Relic Browser
- UI / UX improvement

mana

June 21, 2017
Tweet

Other Decks in Programming

Transcript

  1. 1
    SPAアプリの
    パフォーマンス改善入門
    with Angular
    HRMOS事業部 プロダクト開発
    フロントエンドエンジニア
    黒田学人

    View full-size slide

  2. 2
    自己紹介

    View full-size slide

  3. 3
    黒田学人...
    ● Web系の受託会社
    ○ LAMP
    ○ Backbone.js
    ● Vancouver / Canada
    ○ Art School
    ■ デザイン学んだり
    ■ 仕事したり
    ● BizReach
    ○ HRMOS事業部 フロントエンドエ
    ンジニア
    ○ Angular

    View full-size slide

  4. 4
    フロントエンドの
    パフォーマンス改善とは

    View full-size slide

  5. 5
    パフォーマンスはUXの重要な要素

    View full-size slide

  6. 6
    ユーザー第一に考える

    View full-size slide

  7. 8
    RAILパフォーマンスモデル

    View full-size slide

  8. 9
    ● R : Responseは100ms未満になるように
    ● A : Animationは16ms毎になるように
    ● I : Idleは100ms未満で起きるように
    ● L : Loadは1000ms未満に終わるように

    View full-size slide

  9. 10
    ● ページのロードから表示されるまで
    ○ データダウンロード
    ○ レンダリングツリーのレイアウト
    ● ページが表示されてからの動き
    ○ レンダリングツリーのレイアウト、ペイント
    ○ ユーザーのアクション
    ○ JavaSriptの実行コスト

    View full-size slide

  10. 11
    ● ページのロードから表示されるまで
    ○ データダウンロード
    ○ レンダリングツリーのレイアウト
    ● ページが表示されてからの動き
    ○ レンダリングツリーのレイアウト、ペイント
    ○ ユーザーのアクション
    ○ JavaSriptの実行コスト

    View full-size slide

  11. 12
    ユーザーの使い心地にフォーカス

    View full-size slide

  12. 13
    ブラウザはなぜ遅くなるのか?

    View full-size slide

  13. 14
    Scriptに負荷がかかると遅い

    View full-size slide

  14. 16
    JavaScriptのメモリリーク

    View full-size slide

  15. 17
    ● 不要になったオブジェクトがメモリ領域に存在するこ

    ● メモリ領域が圧迫されることで、ブラウザの実行速
    度が著しく低下する
    ● メモリの回収はGCが動いた時
    ● リロードしたからって全てが回収されるわけではない

    View full-size slide

  16. 18
    オブジェクトのライフサイクル

    View full-size slide

  17. 20
    どのタイミングで開放されるの?

    View full-size slide

  18. 24
    メモリリークのパターン

    View full-size slide

  19. 25
    コンソール
    タイマー
    クロージャ
    循環参照 (DOM)

    View full-size slide

  20. 26
    コンソール
    タイマー
    クロージャ
    循環参照 (DOM)

    View full-size slide

  21. 28
    コンソール
    タイマー
    クロージャ
    循環参照 (DOM)

    View full-size slide

  22. 32
    コンソール
    タイマー
    クロージャ
    循環参照 (DOM)

    View full-size slide

  23. 33
    JavaScriptの関数は、その関数が定義されたコンテキ
    ストとは異なるコンテキスト上にある変数に格納される
    時、その関数自身および関数の定義時のコンテキストが
    一体になった「クロージャ」という特殊なオブジェクトにな
    る。

    View full-size slide

  24. 34
    わかりづらっ!!

    View full-size slide

  25. 40
    アクティベーションオブジェクト

    View full-size slide

  26. 41
    アクティベーションオブジェクトとは関数のコールが発生
    した際に、自動的に生成されるオブジェクト。アクティベー
    ションオブジェクトには、引数、ローカル変数だけでなく、
    argumentsオブジェクト、thisが格納される。

    View full-size slide

  27. 43
    生成される
    アクティベーションオブジェクト
    {
    arguments:,
    this:,
    foo:,
    bar:,
    baz:,
    qux:
    }

    View full-size slide

  28. 44
    スコープチェーン

    View full-size slide

  29. 45
    スコープチェーンとは、変数の参照を解決する際にアク
    ティベーションオブジェクトを辿る仕組み

    View full-size slide

  30. 46
    アクティベーションオブジェクト
    argument
    this
    アクティベーションオブジェクト
    argument
    this
    localBar
    グローバル変数
    globalBar

    View full-size slide

  31. 47
    アクティベーションオブジェクト
    argument
    this
    アクティベーションオブジェクト
    argument
    this
    localBar
    グローバル変数
    globalBar

    View full-size slide

  32. 48
    変数fに対し、明示的にnullをセットしない限り、hoge()内
    部のアクティベーションオブジェクトは保持され続ける。

    View full-size slide

  33. 49
    コンソール
    タイマー
    クロージャ
    循環参照 (DOM)

    View full-size slide

  34. 52
    element(DOM) -> onclick(DOM) -> function(script) -> element(DOM)

    View full-size slide

  35. 56
    WeakMapは、キーに弱参照を保持できる。
    弱参照はGCによって利用されているとみなされないの
    で、自動的に解放される。

    View full-size slide

  36. 57
    DOM要素に何か値を持たせたいけども、
    DOM要素のプロパティを汚したくないときにWeakMapを
    利用できる。

    View full-size slide

  37. 59
    メモリリークを見つけるには

    View full-size slide

  38. 61
    ● タスクマネージャー
    ○ ページで現在使用されているメモリ量を調べる
    ● Performance (Timeline)
    ○ メモリの使用量を時系列に表示
    ● Profiles
    ○ デタッチされた DOM ツリー(メモリリークの一般的な原因)を特定

    View full-size slide

  39. 62
    ● タスクマネージャー
    ○ ページで現在使用されているメモリ量を調べる
    ● Performance (Timeline)
    ○ メモリの使用量を時系列に表示
    ● Profiles
    ○ デタッチされた DOM ツリー(メモリリークの一般的な原因)を特定

    View full-size slide

  40. 65
    ● Memory
    ○ ネイティブメモリを表す。DOM のノードはネイティブメモリに格納され、この
    値が増えている場合は、DOM のノードが作成されている。
    ● JavaScript Memory
    ○ JS ヒープを表す。基本的に見るのはライブ数値(かっこ内のやつ)。 ライブ
    数値は、ページ上のアクセス可能なオブジェクトが使用中のメモリ量を表し
    ている。 この数値が増えている場合は、新しいオブジェクトが作成されてい
    るか、既存のオブジェクトが拡大している。

    View full-size slide

  41. 66
    ● タスクマネージャー
    ○ ページで現在使用されているメモリ量を調べる
    ● Performance (Timeline)
    ○ メモリの使用量を時系列に表示
    ● Profiles
    ○ デタッチされた DOM ツリー(メモリリークの一般的な原因)を特定

    View full-size slide

  42. 69
    1. FPS
    1 秒あたりのフレーム数。緑色の棒グラフが高いほど、FPS も高くなる。グラフ上部の赤いブロックは時間がかかって
    いるフレームを示し、問題を含んでいる可能性がある。
    2. CPU
    CPU リソース
    3. NET
    ネットワークリソース。棒グラフが長いほどダウンロードに時間がかかっている。

    View full-size slide

  43. 70
    ● Keep 60 FPS
    ○ ブラウザは1秒間に60回リフレッシュする
    ○ 60FPSのためには、1フレームあたり16.67msに抑える必要がある
    ○ 一般的には30FPS出てればいい感じらしい

    View full-size slide

  44. 73
    ● JS Heap
    ● Documents
    ● Nodes
    ● Listeners
    ● GPU

    View full-size slide

  45. 80
    ● タスクマネージャー
    ○ ページで現在使用されているメモリ量を調べる
    ● Performance (Timeline)
    ○ メモリの使用量を時系列に表示
    ● Profiles
    ○ デタッチされた DOM ツリー(メモリリークの一般的な原因)を特定

    View full-size slide

  46. 84
    ● Distance
    ○ GC rootからの距離。Windowオブジェクトからの距離
    ● Object Counts
    ○ オブジェクト数
    ● Shallow Size
    ○ 直接参照されているオブジェクトのデータサイズ
    ● Retained Size
    ○ 参照されている全てのオブジェクトの総データサイズ

    View full-size slide

  47. 87
    AngularJSの
    メモリリーク対策

    View full-size slide

  48. 88
    ● Event Handlerを解放してあげる
    ● Watcherを解放してあげる
    ● Serviceのコールバック内で$scopeを使わない

    View full-size slide

  49. 89
    ● Event Handlerを解放してあげる
    ● Watcherを解放してあげる
    ● Serviceのコールバック内で$scopeを使わない

    View full-size slide

  50. 92
    ● Event Handlerを解放してあげる
    ● Watcherを解放してあげる
    ● Serviceのコールバック内で$scopeを使わない

    View full-size slide

  51. 95
    ● Event Handlerを解放してあげる
    ● Watcherを解放してあげる
    ● Serviceのコールバック内で$scopeを使わない

    View full-size slide

  52. 98
    ● Third Parties

    View full-size slide

  53. 101
    Angular2の
    メモリリーク対策

    View full-size slide

  54. 106
    Change Detectionをスキップして高速化

    View full-size slide

  55. 110
    イベントが起こると毎回すべてのコンポーネントで
    Chande Detectionを走らせなければならない

    View full-size slide

  56. 112
    チェックの回数を減らしたい

    View full-size slide

  57. 113
    Immutable オブジェクト

    View full-size slide

  58. 117
    Observable オブジェクト

    View full-size slide

  59. 118
    ImmutableのようにObservableは変更があっても
    新しい参照は与えられない。その代わりに変更に反応
    するためにsubscribeが使用できる。

    View full-size slide

  60. 121
    どうすればAngularに変更を知らせることができる?

    View full-size slide

  61. 124
    NgZoneでChande Detectionが走っているか確認

    View full-size slide

  62. 126
    angular-performance-checklist
    https://github.com/mgechev/angular-performance-checklist#runtime-optimizations

    View full-size slide

  63. 127
    UI / UXのチューニング

    View full-size slide

  64. 128
    振る舞いやUIを変更することで
    ユーザーの体感速度を上げること

    View full-size slide

  65. 129
    ● RAILパフォーマンスモデルでは、ユーザーのアクショ
    ンに対するレスポンスの指標は100ミリ秒以内
    ● ロードが始まってからユーザーが操作可能になるまで
    の時間は1000ミリ秒以内にすべき

    View full-size slide

  66. 130
    1秒を超えるような処理や読み込みを行う場合には、待
    ち時間であることを表すインジケータやアニメーションな
    どを返してあげること。
    そして、ユーザーに待たされている感覚を与えないこと。

    View full-size slide

  67. 131
    ● インターフェイスプレビュー
    ○ ローディング中に仮のコンテンツを表示しておく
    ● ローディングアニメーション
    ○ マイクロインタラクション

    View full-size slide

  68. 135
    New Relic Browserで
    SPA監視

    View full-size slide

  69. 137
    定期的に観測することで、問題のあるページ、処理を洗
    い出したい

    View full-size slide

  70. 138
    ● Ajaxのレスポンスタイムパフォーマンス
    ● ページレンダリングの時間がわかる
    ○ 遅いページが大体わかる
    ● ブラウザ毎のパフォーマンスがわかる
    ● エラー監視

    View full-size slide