永遠にWIP

見に覚えのないWorkerが立ち上がっていた話

Frontend
React

TL;DR

デベロッパーツール見るの大切だねという話。

はじめに

ある日デベロッパーツールでパフォーマンス周りの調査をしていたら見に覚えのないWorkerが立ち上がっていました。
20MB ~ 50MB程度のメモリーを使用しており、ちょっと気になったため調査することにしました。

調査

今回の場合、問題のページではWorkerを使っていないと思ったため、おそらく他のページで使ったWorkerが残ってしまっているのではないかと思い以下のような調査方法をしました。

  1. ページをリロードする
  2. デベロッパーツールのMemoryタブを見てWorkerが立ち上がっているかどうかを確認する
  3. 他のページに移動し、同様に2を行う

結果としてはMapboxを使っているページでWorkerが立ち上がり、他のページに移動してもWorkerがkillされないことがわかりました。
問題のプロジェクトではReactでMapboxを簡単に扱うためのライブラリであるreact-map-glを使用していたため、Mapboxかreact-map-glのどちらかに問題があると考えライブラリ側の調査にいきました。

しかし、流石にいきなりソースコードを読みに行くのはちょっと辛いので、公式ページのexampelで同様の調査をしました。
結果としては、Mapbox側ではMapがunmoutされた段階でWorkerがkillされるのに対して、react-map-glではkillされないということがわかりました。

原因究明

これはOSSコントリビュートチャンスじゃんということでウキウキしながらreact-map-glのソースコードを読みにいきました。

読んでいくとreact-map-glではmapbox-glをラップしてReact用に最適化したMapboxクラスがあり、コンポーネント側でこのクラスを使っていることがわかりました。
このクラスにはMapboxの立ち上げたWorkerを再利用するためにreuseMapsというオプションが存在します。
一応公式の説明は以下のようなものになります。

reuseMaps is provided for applications that create and destroy maps, to help work around a mapbox-gl resource leak issue that can lead to a browser crash in certain situations.

このオプションがtrueのときはWorkerが再利用され続けるため、「私がしっかりドキュメント読んでなかっただけなのでは?」となりましたが、よく見るとこのオプションはデフォルトでfalseになっており、問題のあったプロジェクトでもfalseにしていました。
falseのときはWorkerを適切にkillしなければいけないためバグであることが判明しました。

ということで修正PR投げて無事解決し、最新バージョンに取り込まれました。

https://github.com/visgl/react-map-gl/pull/1555

さいごに

今回の問題はデベロッパーツールを見ていなかったら気づかない問題だったと思います。
日常的に計測したりするのは非常に大切なんだなと身にしみて感じました。

© 2020 DuGlaser