Mobile Factory Tech Blog

技術好きな方へ!モバイルファクトリーのエンジニアたちが楽しい技術話をお届けします!

駅メモ!の地図をiOS16リリースに伴って負荷軽減した話

はじめに

id:wgg00sh です。 この記事では、2022年9月にリリースされた iOSの新バージョン 16.0 に向けて、駅メモ!の地図クライアントで行った対応について紹介します。

駅メモ!の地図について

昨年度のアドベントカレンダー で紹介していますが、駅メモ!のアプリ内地図は mapbox-gl-js を使用しています tech.mobilefactory.jp

iOS16で発生していた問題

2022年9月頃、正式にリリースされる前のβ版iOS16で駅メモ!の動作を見ていたところ、意図しない表示になることがありました。 そして、特に地図を開いた直後にその問題が発生しやすいとわかったため、自分は地図の負荷を減らす方向で問題の軽減を進めました。

mapbox-gl-jsの Safari における問題

こちらの issue に問題の詳細が書かれています。 mapbox-gl には、 map.remove() という終了用のクリーンアップを行うAPIがありますが、この処理に問題があり Safari では正常にクリーンアップされずメモリリークが発生してしまいます。 ここでは Safari と書いていますが、 iOSにおいてはサードパーティ製のブラウザもSafariと同一の WebKit を使用しているので、 例えばWebブラウザで動作するアワメモ!を iOS Chrome でプレイしていてもこの問題は避けられません。 また、駅メモ!では mapbox-gl-js の v1.13.0 を使用していましたが、当時バージョンの v2.10.0 でもこの問題は解消されていません。

iOS16対応以前 (~2022/09)

このSafariの問題に対する解決策が見つかっていなかった当初は駅メモ!内で地図の開閉を繰り返すことで動作が極端に重くなったり、Webページがクラッシュして強制的にブラウザがリロードされてしまう事がありました。 そこで地図画面に以下の暫定的対処をしていました。

地図を閉じた際にmapbox-glのインスタンスを破棄せず全て保持して、再度地図を開く場合にはそのインスタンスを再利用するというものです。

これによって地図を複数回開くことによるメモリリークを防ぐことはできたものの、地図を使用していない間もメモリを食っておりパフォーマンス的にはあまり良い状態とは言えませんでした。 iOS16ではこの状態で駅メモ!をプレイし続けると、他の問題も合わせて表示の不具合が発生しやすいとわかったため、この問題を解消することになりました。

解決

この問題に対して他にも苦戦していた方がいたのか、偶然同時期に 同じ問題に関するPR が他の方から上げられました。 diff を見ると、webglcontextlost などの webgl周りのイベントを破棄できていなかったり、canvas の初期化ができていなくてGCが機能していなかった様に見えます。 このPRと同等の内容を、 駅メモで使用しているmapbox-gl-js v1.13 に適用して解決を図ります。

駅メモ!で動作を確認

修正を適用した mapbox-gl を使用して、実際に駅メモ!上での動作を確認してみます。

修正前 修正後

Safariのインスペクタを開いた状態で地図の開閉を繰り返し行ったところ、修正後は地図画面を閉じると使われなくなった Canvas が削除されるようになりました。 また、開閉を繰り返すことでブラウザが強制リロードされる問題も発生しなくなることが確認できました。

終わりに

iOS16がリリースされるにあたって、駅メモ!で行った対応は地図だけでなく他にもたくさんありましたが、今回は自分が担当した地図の問題解消について紹介しました。 とはいえ偶然同時期に同じ問題を解消された方が居てそれを利用させていただいた形でしたので、このPRが上がっていなければiOS16 がリリースされるまでに解消するのは困難でした。

また、今回導入した実装は現状 iOS16 で駅メモ!を実行した場合にのみ動作するようになっています。 iOS15以前では引き続きmapbox-gl のインスタンスを保持して、地図を開き直す場合には再利用する形になっています。