2017-12-22 11 views
8

私はビルドしているWebアプリケーションのかなり良いサイズのjavascript(react/reduxではjqueryはありません)コードベースを持っていますが、UI内の特定のパネルを繰り返し開いて閉じると、リスナーの数Chromeのパフォーマンスのタイムラインに沿って増加し続けています。アイドル(ちょうど開封後/パネル束を閉じる)、おそらくことを期待して、私が座っページとの良好な分または2のためのChromeのパフォーマンスモニタの実行を許可してい Graph of timelineイベントリスナーの追加先を追跡するにはどうすればよいですか?

グラフは次のようになりますリスナーはガベージコレクションを行いますが、そうではありません。私はこのプロセス中に他のタブに切り替えました。また、タブが背景になっているときにリスナーがガベージコレクションを取得することを期待していましたが、残念ながらそうではありません。

したがって、登録されていない一部のリスナーは登録されていないと思われます。

これは、主に2つの質問に私をリード:

  1. 私の仮説は、リスナーが追加取得され、決して 結合していないが賢明なようだ、またはそれ以上があることを私は にこの疑惑を確認するために行うことができますか?
  2. 私の疑惑が正しいと仮定すると、 は、イベントリスナーがあるコードを追跡するのにどうすればいいですか? が追加されていますか?私はすでに以下を試しました:
    • 問題のパネルを開くコードを見て、それがリスナーを追加する場所を見て、それらの部分をコメントアウトしてパフォーマンスグラフに変更があるかどうかを調べます。変更はありません。その後、(参照#このconsole.traceを実行させるすべてのコード部分をコメントアウト、でもこれをやった後

 

var f = EventTarget.prototype.addEventListener; 
EventTarget.prototype.addEventListener = function(type, fn, capture) { 
    this.f = f; 
    this.f(type, fn, capture); 
    console.trace("Added event listener on" + type); 
} 

:そのようにaddEventListenerプロトタイプをオーバーライド

  • 1)パネルのオープン/クローズ時にconsole.traceが表示されなくなるため、パフォーマンスグラフのリスナーが同じように増加しています。何かがリスナーを増やしています。リスナーを追加できる他の方法があることは理解していますが、これらの可能性をすべて傍受したり、Chromeのデバッガにログインさせる方法はわかりません。

    編集: -

    function printListenerCount() { 
        var eles = document.getElementsByTagName("*"); 
        var numListeners = 0; 
        for (idx in eles) { let listeners = getEventListeners(eles[idx]); 
         for(eIdx in listeners) 
         { 
          numListeners += listeners[eIdx].length; 
         } 
         console.log("ele", eles[idx], "listeners", getEventListeners(eles[idx])); 
        } 
        console.log("numListeners", numListeners) 
    } 
    

    が、私はこれを実行します: https://developers.google.com/web/tools/chrome-devtools/console/events

    は、私は、次の関数を作っ コメントでcowbertの提案では、私は、このページを見ていましたパネルを数回開いたり閉じたりした後に機能しますが、残念ながら "numListeners"の数字は変わりません。 numListenersの図が変更された場合は、パネルの開閉の前後で結果を比較して、追加のイベントリスナーが登録されている要素が見つかったパネルを閉じることができますが、残念ながらnumListenersは変更されません。

    https://developers.google.com/web/tools/chrome-devtools/console/eventsに記載されているmonitorEvents()APIもありますが、関数 を呼び出すには、監視するDOM要素を指定する必要があります。このような状況では、どのDOM要素に余分な リスナーがあるのか​​わからないので、monitorEvents()呼び出しが実際にどのように役立つのかよく分かりません。上記のprintListenerCount関数を に書き込んだのと同様に、すべてのDOM要素にアタッチすることができますが、私はprintListenerCount()で何が起こったのか、同様の問題に遭遇していると推測します。 問題のリスナーを説明します。

    その他の注記: これはやや複雑な反応です(技術的にプレアクトな)アプリケーションです。ほとんどの反応系ベースのアプリケーションと同様に、コンポーネントはオンザフライでマウント/アンマウント(DOMへの挿入/削除)されます。私はこれがちょっとトリッキーな "迷子イベントハンドラ登録"を追跡することを発見しています。だから、私が本当に望んでいるのは、このような大規模なプロジェクトや複雑なプロジェクトの "Strayイベントハンドラ"を追跡する方法に関する一般的なデバッグアドバイスです。 Cプログラマとして、私はgdbを開き、パフォーマンスグラフの "リスナー"番号を増加させる可能性のあるすべてにブレークポイントを設定します。私はJavaScriptの世界でそのアナログのアナログがあるかどうかは分かりません。たとえそれがあっても、それをどうやって行うのか分かりません。どんなアドバイスも大歓迎です!

  • +1

    chromeのmonitorEvents()APIを見てみましたか? https://developers.google.com/web/tools/chrome-devtools/console/events – cowbert

    +0

    ありがとう、私はそれを見て、私のOPにメモを追加しました。 – Andrew

    +0

    コード内のaddEventListenerのすべてのインスタンスを検索し、それらにブレークポイントを置くことができます。あなたが試してみる前に誰かが同じことをしない限り、プロトタイプの交換で得たものと大きく異なるべきではありません... – jcaron

    答えて

    0

    ご意見ありがとうございます。私はこれを理解し終わった。私のOPから

    :もっと私はこの疑いを確認するために行うことができ

    1. は、リスナーが追加取得している私の仮説を行い、決して結合していないが賢明なようだ、またはありますか?

    この質問に対する答えは、次のとおりです。この仮説は賢明ではありません。リスナーはまだガベージコレクションを受ける機会がありませんでした。あなたが思っているよりも時間がかかります。 パフォーマンスタイムラインを記録しているときに、パフォーマンスタブのゴミ箱アイコンをクリックしてガベージコレクションを強制することができませんでした(タイムライン記録を開始するのに使用された同じタブ)。 UIパネルを繰り返し閉じる/開いた後にこのアイコンをクリックすると、余分なリスナーが完全になくなりました。タブをバックグラウンド化し、私はOPで述べたように数分待って、単純にガベージコレクションのための十分な時間はありませんが、どうやら Performance timeline with manual GC

    :グラフは今ディップは、私は、ゴミ箱のアイコンをクリックした瞬間であることと、このようになりますそれ自身で発生する。それ以上に時間がかかります。

    私はOPを書いたときにごみ箱アイコンを使って手作業でゴミを収集することができませんでした。最初に見たことのある野生のガチョウの追跡をする前に、パフォーマンスの問題。

    +2

    ここで、あなたが誤解した/誤解したグラフの「パフォーマンス上の問題」はありませんか?つまり、実際に測定されたパフォーマンス上の問題はありませんでした。あなたはそれがあると思って、しばらくテールを追うことになりました。これは誰にでも起こりますが、その解決策は、ツールUIのボタンを見つけて、想像上の問題を解消することではなく、実行時環境とツールがあなたに伝えていることをよりよく理解しようとすることです'あなたが答えとして提示した結論が良いものであるかどうかは分かりません。 – pvg

    +0

    オブジェクトを "削除"するとき、デフォルトでプリアクト/それを再描画したい場合に備えてキャッシュしていますが、ハンドラがまだバインドされているためキャッシュされているのでしょうか? – cowbert

    +0

    私のオペレーションでは、次の質問を投稿しました。「リスナーが追加されており、決して縛られていないという私の仮説は賢明であるか、この疑惑を確認するためにもっとできることはありますか?その質問への答えは、「実際のパフォーマンスの問題が間違っていたというあなたの疑念」であることが判明しました。私は、私が「仮説は賢明ではない」と言ったとき、私が答えでそれをかなり明確にしたと思った。それが不明な場合は、理由を指摘できますか?ありがとう。 – Andrew

    関連する問題