国家の芸術、第2部:ガベージコレクション Mendix クライアント

メインコンテンツへスキップ

国家の芸術、パート 2: ガベージ コレクションのメカニズム

このブログを読む前に、まずクライアント状態の紹介を読むことを強くお勧めします。 国家の芸術 パート 1.

パート 2 では、クライアント ステートでのオブジェクト管理の仕組みについて詳しく説明します。非常に抽象的な概念を扱うので、この記事を読むときは温かい飲み物と脳を活性化させるスナックを近くに置いておくことをお勧めします (頭を悩ませるオブジェクト管理のアイデアについては、個人的にはチップスを食べるのが好きです)。

免責事項:このブログ投稿は Mendix 7.23.7と8.0。ガベージコレクションの動作は他のリリースでは異なる場合があります。このブログでは、 Mendix アプリはランタイムと通信するため、より優れたアプリをモデル化し、アプリの問題をより効果的にトラブルシューティングできます。

1. ガベージ コレクションとは何ですか? なぜ必要なのですか?

アプリケーションをモデリングしながら、オブジェクトの作成、コミット、ロールバック、および削除を行います。このようなオブジェクトを UI に表示したり、マイクロフローやナノフローに渡したり、変更したり、カスタム ウィジェットで操作したりできます。作業中のオブジェクトには永続的なものもあれば、そうでないものもあります。永続不可能なオブジェクトは常にメモリ内に存在し、データベースに保存されることはありません。また、新しい永続可能オブジェクトをコミットすることもできません。コミットすると、メモリ内に存在し、実質的に永続不可能になります。

典型的なユーザーセッションでは、ユーザーは何時間もアプリケーションを操作して数十ページを訪問し、複数のオブジェクト(永続的または非永続的)を作成します。これらのオブジェクトはクライアント状態の一部となり、ブラウザのメモリ領域を占有するため、時間の経過とともにアプリの速度が低下する可能性があります。 Mendix 開発者は、作成したオブジェクトをすべて削除する必要はなく、アプリケーションにコミットしなくても、パフォーマンスを低下させることなくアプリケーションは動作します。これはどのように可能でしょうか? Mendix ユーザーが 10 ページ前に作成した非永続オブジェクトはどうなりますか? 永続オブジェクトに加えられた変更についてはどうなりますか?

ガベージ コレクション メカニズムは、これらの質問に対する答えです。

ゴミの日!
ゴミを捨てる時間です。

その Mendix クライアントはオブジェクトとその状態の変化を分析し、不要だと判断した場合は削除します。このプロセスの目的は、メモリに保持される状態を最小限に抑えることです。 Mendix アプリに必要なオブジェクトは、以下に詳述するいくつかの基準に基づいて決定されます。

2. ガベージコレクションはいつ行われますか?

私の近所では、たいてい火曜日の朝に行われます。 Mendix アプリでは、アプリの使用中にバックグラウンドでガベージ コレクションが行われます。定期的に実行され、すべてのオブジェクトとその状態の変化を分析し、不要であると判断されたオブジェクトや変更を削除します。

3. ガベージコレクションが行われているのを確認できますか?

状態検査のショートカット(Ctrl + Alt + G) を実行してクライアントの状態を調べ、ガベージ コレクションを確認することもできます。ただし、これからコレクションされるオブジェクトを確認するには、少し運が必要です。多くの場合、確認できる前にコレクションが実行されます。ここでは、ガベージ コレクションがまだ開始されていないため、コレクションされるオブジェクトを確認できます。

GC 前のオブジェクトの状態ビュー

ほんの数秒で、このオブジェクトは見えなくなります。

ガベージコレクションが発生したときにどのオブジェクトが削除されるかを確認するための特別な設定を有効にすることもできます。これを行うには、新しい データ セクション logCleanupStatistics: 真プロパティを 道場設定 アプリケーションで設定されたオブジェクト テーマ/index.html ファイル。コードは次のようになります。

dojoConfig = {
    baseUrl: "mxclientsystem/dojo/",
    cacheBust: "{{cachebust}}",
    rtlRedirect: "index-rtl.html",
    data: {
      "logCleanupStatistics": true
    } 
};

このセクションを追加すると、ガベージ コレクションが発生するたびに情報メッセージが追加されます。

GC統計

免責事項: 上記の構成は公開されておらず、予告なく変更または削除される可能性があります。

4. ガベージコレクションはどのように機能しますか?

これで、アプリケーションで作成またはロードされた不要なオブジェクトと変更がクライアント状態から削除され、アプリケーションを高速に実行し続けることができることがわかりました。しかし、これはどのように機能するのでしょうか。

その質問に対する概念的な答えは簡単です。 Mendix クライアントは、オブジェクトがどのコンポーネントに必要であるかをいつでも知ることができる必要があります。必要でない場合は、状態から削除できます。 Mendix オブジェクトは関連付けを通じて1つ以上のオブジェクトを参照することができます(または参照されることができます)。 Mendix クライアントは依存オブジェクトも追跡する必要があります。

これらの概念が実際にどのように機能するかを詳しく見てみましょう。 Mendix クライアント。

5.サブスクリプション

プラン契約確認 ガベージコレクションの鍵となるのがサブスクリプションシステムです。サブスクリプションシステムは Mendix クライアントを使用すると、変更があったときに通知を要求できます Mendix オブジェクトまたはその属性。カスタムウィジェット用のシンプルなAPIのように見えますが、実際には Mendix クライアントは、社内でサブスクリプションをよく使用します。次に、社内での使用例をいくつか示します。

  • データ ビューはオブジェクトをロードするたびに、ロードされたオブジェクトをサブスクライブして、特定の状況 (たとえば、オブジェクトが削除された場合) に関する通知を受信できるようにします。
  • ほとんどの入力ウィジェットは、操作しているオブジェクトの更新を取得するためにサブスクリプションに依存しています。これにより、どこか他の場所で値が変更されたときに値を更新できます。Dojoウィジェットは、多くの場合、手動でオブジェクトをサブスクライブします。ただし、 プラグイン可能なウィジェット サブスクリプションは Mendix クライアント。
  • その Mendix クライアントは、ページ上の条件付きの表示および編集可能性のルールのオブジェクトをサブスクライブし、関連するオブジェクトまたは属性が変更されたときに条件を再評価します。
  • パラメータを持つテキスト ウィジェットは、そのオブジェクトをサブスクライブします。テキスト ウィジェットは、テンプレート値が関連付けを超える場合、すべての中間オブジェクトもサブスクライブするため、関連付けが変更されるたびにウィジェットを更新する必要があることを認識します。

サブスクリプションは、ガベージ コレクション メカニズムによって入力として扱われ、サブスクライブされたオブジェクトがアプリで必要であり、収集する必要がないことを示します (コンポーネントまたはウィジェットが引き続きそれを使用しているか必要としています)。

その Mendix クライアントは、通知コールバックを使用しなくても、特定の時点でUIに表示されないオブジェクトも購読します。これは、 Mendix クライアントはそれらのオブジェクトを必要とします。次に、このような動作の例をいくつか示します。

  • 表現するオブジェクト $現在のユーザー (NAIST) と $現在のセッション 常に購読されている Mendix クライアントは、ユーザーがアプリを使用する限り存続し、いつでもアプリケーションによって必要になる可能性があるためです。

    注:a $現在のセッション オブジェクトはセキュリティ上の理由からクライアントに返送されることはありません。 Mendix クライアントは引き続きサブスクライブします。 その理由については後述します。

  • データグリッドのデータソースマイクロフローは、データグリッドが1ページに表示できる以上のオブジェクトを返す場合があります。これらのオブジェクトはクライアント状態の一部になります。 Mendix クライアントは、ガベージ コレクションによって誤ってクライアント状態からオブジェクトが削除されないように、それらのオブジェクトすべてをサブスクライブします。

  • パラメータを持つページが閉じられると、ガベージコレクションによってパラメータオブジェクトがクライアント状態から削除される可能性があります(そのオブジェクトが不要になったと仮定)。このようなページパラメータは非永続的なオブジェクトになる可能性があり、削除すると永久にアクセスできなくなります。しかし、ユーザーはブラウザの戻るボタンを使用して戻ることができるため、パラメータオブジェクトは状態に保持される必要があります。そのため、 Mendix クライアントは最後の 5 ページのページ パラメータ オブジェクトをサブスクライブします。そのため、ガベージ コレクションではそれらは削除されません。

5.1 オブジェクトが状態に保持されている理由を確認できますか?

特定のオブジェクトがなぜその状態に維持されているのかは、 Ctrl + Alt + G ショートカット。以下の例では、 アーティスト オブジェクトは現在のページのウィジェットによって購読されています。 ヌル のエントリ 購読済みウィジェット 配列。つまり、 Mendix クライアント内部またはカスタムウィジェットから:

サブスクリプションのある州

したがって、サブスクライブされたオブジェクトは、サブスクライブされている限りその状態に保持される必要があることは明らかです。

それはすべてですか?

6. 到達可能性の重要性

前述のように、購読したオブジェクトだけを保持するだけでは十分ではありません。 Mendix クライアントは関連付けを考慮する必要があります。ここでは非永続的な Mendix オブジェクトと呼ばれる オブジェクトA クライアント状態の内部:

箱

このオブジェクトはサブスクライブされていないため、ガベージ コレクションが発生したときに状態から削除される可能性があります。

もう一つのオブジェクトを追加しましょう。これは非永続的なオブジェクトです。 オブジェクトB:

2つの箱

どちらのオブジェクトもサブスクライブされていないため、クライアント状態から削除できます。

さて、想像してみて オブジェクトA 関連性があり、 オブジェクトB その値として:

ボックスオブジェクトaがボックスオブジェクトbを指している

この状況では何も変わりません。どちらのオブジェクトもサブスクライブされていないため、クライアント状態から削除できます。

ここに オブジェクトA 購読するには mx.data.subscribe API(赤い光に注目してください) オブジェクトA):

箱が光るようになりました

この状況では、両方のオブジェクトをその状態に保持する必要があります。なぜでしょうか?

オブジェクトA サブスクライブされているため、ガベージ コレクション メカニズムではサブスクライブされたオブジェクトは削除されないため、収集されるべきではありません。

オブジェクトB 購読されていないが、それは収集できるという意味ではない。 オブジェクトA 参照します。受け入れるマイクロフローを考えてみましょう オブジェクトA パラメータとして。このマイクロフロー内では、 オブジェクトB 取得されるのは アクティビティを取得 Association Retrieve型を使用します。ガベージコレクションによって削除された場合 オブジェクトB 状態から、このマイクロフローはそれを取得できません。

したがって、ガベージコレクションもこれを考慮して、 オブジェクトB クライアント状態では、次の理由でこれを行う必要があります。

  • オブジェクトB 「到達可能」なのは オブジェクトA: それらは関連しています。マイクロフローまたはナノフローの取得アクティビティは、 オブジェクトA.
  • オブジェクトB 非永続的であるため、マイクロフローの取得アクティビティによってデータベースから読み込むことはできません。永続的なエンティティ (コミットされている) であれば、マイクロフローはアプリケーション データベースからそれを取得できます。

新しいオブジェクトを追加してみましょう。 オブジェクトC ガベージコレクションはいつ行われますか?

3つの箱aとcは両方ともbを指している

オブジェクトC 州内に保管されるべきである。なぜなら、それは オブジェクト A -> オブジェクト B -> オブジェクト C.

それも可能です オブジェクトA 同じ関連付けの値として2つの異なるオブジェクトを参照することができます。これはどのように起こるのでしょうか? オブジェクトA 関連する団体と提携して行われる オブジェクトB同じ関連付けをポイントすると オブジェクトD コミットせずに、この関連付けに「変更」を導入します。この場合、 オブジェクトA 同じ関連付けに対してコミットされた値と変更された値の両方を認識します。

ボックスaがボックスbとdを指し示している

ガベージコレクションはこのケースを考慮し、両方を保持します オブジェクトB (NAIST) と オブジェクトC 州内では、両方とも オブジェクトA.

上記の例はすべて、非永続オブジェクトに関するものです。永続オブジェクトを追加してみましょう。これらは、明るい青色の背景で表されます。

たくさんの箱

ガベージ コレクションが発生したときに、各永続化オブジェクトに何が起こるかを確認してみましょう。

オブジェクトB 以下の理由により収集しないでください。

  • その (新しい) 名前の末尾のサフィックスは、まだコミットされていないことを示し、実質的にオブジェクトを非永続的なオブジェクトのように動作させます。このオブジェクトはメモリ内でのみ見つかります。
  • 以下から参照されています オブジェクトA、それを「到達可能」としてマークします。参照されていなかった場合、ガベージ コレクションによってクライアント状態から削除される可能性があります。

オブジェクトC 以下の理由により収集しないでください。

  • その ** 名前の末尾に「」が付いているものは、コミットされていない属性/関連付けの変更があることを示します。このような変更は、 オブジェクトC コミットまたはロールバックされます。
  • 以下から参照されています オブジェクトA、それを「到達可能」としてマークします。参照されていなかった場合、ガベージ コレクションによってクライアント状態から削除される可能性があります。

オブジェクトD 以下の理由で収集される可能性があります。

  • これはコミットされたオブジェクトです( (新しい) サフィックス)。
  • また、変更も一切ありません( ** 名前にちなんで付けられました。

これは、 オブジェクトD コミットされていない属性値は含まれておらず、必要なときにいつでもアプリのデータベースで見つけることができます。そのため、ガベージコレクションメカニズムは、クライアントの状態からそれを削除します。 オブジェクトA.

オブジェクトE サブスクライブされたオブジェクトから参照されていないため、ガベージ コレクションの対象となります。つまり、まったくアクセスできません。ガベージ コレクションは、コミットされていない属性/関連付けの変更を含め、このオブジェクトをクライアント状態から削除できます。そのオブジェクトにはアクセスできなくなったため、オブジェクトを削除しても安全です。

前のセクションで述べたように $現在のセッション (システム.セッション)は常に購読されています Mendix クライアントは、状態には到達しません。理由は推測できます。状態には、クライアントを参照するオブジェクトがある可能性があります。 $現在のセッション、したがってそこから「到達可能」です。そのため、それらも状態に保持される可能性があります。

7. 結論

上記の説明を踏まえて、ガベージ コレクション プロセスをさらに次のように要約できます。

ガベージ コレクションは、状態内のすべてのサブスクライブされたオブジェクトから開始され、依存関係グラフを構築することで、それらの関連付けを通じてすべての「到達可能な」オブジェクトを検索します。このグラフを分析することで、各オブジェクトと (存在する場合) クライアント状態におけるその変更を保持するか破棄するかを決定します。

7.1 状態に保持されるオブジェクトはどれですか?

  • サブスクライブされたすべてのオブジェクトは状態に保持されます。
  • サブスクライブされたオブジェクトから「到達可能な」すべてのオブジェクトは、次のいずれかのカテゴリに該当する場合に保持されます。
    • データベース内で見つからないため、非永続オブジェクトです。
    • 作成されていますが、まだアプリのデータベースにないため、まだコミットされていない永続オブジェクト。
    • コミットされているが変更を含む永続オブジェクト。変更はまだデータベースに含まれていないが、マイクロフローで必要になる可能性があるためです。

7.2 状態から削除されるオブジェクトはどれですか?

  • サブスクライブされたオブジェクトからアクセスできないオブジェクトは破棄されます。このようなオブジェクトは、多くの場合、ユーザーが以前にアクセスしたページからのものです。
  • サブスクライブされたオブジェクトからまだアクセス可能だが、状態がデータベースと同じオブジェクトは破棄されます。このケースは、データベースにコミットされ、変更されていない永続可能オブジェクトに適用されます。オブジェクトが必要な場合は、データベースから読み込むことができます。

上記の説明を読んだ後、少し無気力になったように感じるかもしれません。

困惑した子猫のGIF

説明はこれで十分です。学んだことを実践してみましょう。

8. ガベージコレクションゲーム

先ほど、ガベージ コレクションのメカニズムについて図を使って説明しました。今度は、ゲームをプレイして、そのメカニズムを理解したかどうかを確認します。ゲームのシナリオは、GC メカニズムの内部ユニット テストから取得されています。正しい答えを推測できるかどうか試してみましょう。

ゲームはシンプルです。以下にクライアントの状態の表現を示します。凡例は上記と同じです。次に例を示します。

ボックス

このグラフから、次のようなことがわかります。 オブジェクト1:

  • 永続的なエンティティです(青い背景)
  • 購読されています(周囲が赤く光っています)
  • まだデータベースにコミットされていません(名前の末尾に「(new)」が付いています)
  • 変更が含まれています。( ** 名前の最後に

この事例を見た後、次のような疑問が湧くかもしれません。「新しい」オブジェクトは変更できるのでしょうか? オブジェクトが作成されると、その属性はドメイン モデルで定義できる「デフォルト」値を保持するため、変更が可能です。これらのデフォルト値は、属性の現在の「コミットされた」値になり、それらに加えられた変更はすべて状態に保存されます。

オブジェクトは、関連付けを通じて相互に参照することもできます。

2つの箱

上の写真からわかるように オブジェクト1 設定された値に関連付けられている オブジェクト2このゲームでは、関連付けの名前も基数も重要ではないため、指定しません。この矢印は、 オブジェクト2 でアクセスできます アクティビティを取得 マイクロフローで 協会 取得タイプ。

ゲームには 7 つのレベルがあります。各レベルは、ガベージ コレクションが発生する前の「クライアント状態」の現在の状態を表します。あなたの目的は、ガベージ コレクションが発生したときに、状態内のどのオブジェクトを保持し、どのオブジェクトを状態から削除するかを決定することです。その後、「回答を表示」をクリックすると、結果が表示されます。その後、次のレベルに進むことができます。

ゲームを始めましょう!


ゲームを楽しんでいただけたでしょうか?これで、 Mendix クライアントは状態をクリーンアップします。ガベージ コレクションを念頭に置きながら、より優れたアプリをモデル化するためのヒントをいくつか示します。

9. ベストプラクティス: モデリング中にガベージコレクションを考慮する

9.1 データソースから返されるオブジェクトが多すぎないようにする

何千ものオブジェクトを返すマイクロフロー ソースを含むリスト ビューを想像してください。これらのオブジェクトはすべて状態に保持されますが、リスト ビューではページング構成に応じて、一度にそれらのごく一部しか表示できません。このケースは、ナノフロー データ ソースと関連付けデータ ソースにも当てはまります。このアプローチの代わりに、大規模なデータ セットに高度に最適化された XPath またはデータベース データ ソースを使用してください。現在のページに表示できるデータのみが読み込まれます。

9.2 大きなエンティティを小さなエンティティに分割する

大きなオブジェクトを操作すると、アプリの状態のサイズが大きくなります。大きなオブジェクトは、変更が 1 つだけであったり、属性の 1 つのみがサブスクライブされている場合でも、全体がメモリに保存されます。このようなオブジェクトを分割すると、特に非永続的なオブジェクトの場合、ガベージ コレクションに役立つ場合があります。このように、ガベージ コレクション アルゴリズムは、上記の条件を満たす未使用の小さなオブジェクトを削除できます。

9.3 「スターオブジェクト」を作成しない

「スターオブジェクト」とは、何百もの他のオブジェクトから参照されるオブジェクトのことです。たとえば、 検索結果 オブジェクトは500個あります 検索結果項目 それを参考にして、 検索結果 スターオブジェクトになります。 検索結果 またはのいずれかの 検索結果項目 オブジェクトによっては、すべてのオブジェクトがその状態に保持される可能性があります。すべてのオブジェクトが非永続的であるか、変更が含まれている場合、このパターンは多くの場合問題になります。

このようなオブジェクトを扱う必要がある場合は、手動でコミットまたは削除するか、関連付けの値をスターオブジェクトに設定して 空の 使用後は必ず保管してください。

9.4 開発中の国家の規模を確認する

 Ctrl + Alt + G 状態のサイズを確認するためのショートカットです。状態の内容を確認することは、大きなページで作業する場合に特に重要です。たとえば、カスタム ウィジェットでオブジェクトの登録を解除し忘れたために、オブジェクトがそこに残っていることに気付く場合があります。

9.5 ランタイムログで余分な状態を確認する

その Mendix クライアントは、ランタイム リクエストに状態の必要な部分を送信し、クライアントから送信されたオブジェクトの数が特定のしきい値を超えると警告が記録されます。このような警告が表示された場合は、そのページを再度表示して、状態に保持されているオブジェクトが多数ある理由を調べる必要があります。

この記事を読んで楽しんで、役に立ったと感じていただければ幸いです。コメント、質問、または一般的な賞賛があれば、私に連絡してください。 こちら.

言語を選択してください