100万ページの巨大projectで激しくリンク記法を編集するとout of memoryでChromeがクラッシュしてしまう
まずはout of memoryを解決します
他の問題として、100万ページあるとQuickSearchが遅い等もあるけど、そっちは扱わない
実装
ローカルに20万ページ作ってみた
ちょっと重かった
まだ足りない。ある会社は30万ページ + 5万空ページある とりあえずローカルに100万ページ作ろうshokai.icon
すごいyuiseki.iconteramotodaiki.icon
こうなる…?
https://nota.gyazo.com/d3541d57117b8a6afc6ca745006041e2
なりましたshokai.icon
https://scrapbox.io/files/652a39394d2a72001cbb98e2.png
https://scrapbox.io/files/652a393cef4885001b0596d1.png
負荷をかけてout of memoryを発生させる方法
準備
mainブランチにて
Workerの処理待ち中にlinks changeが来る確率が高まる
chrome devtoolを開いておく
巨大projectを開き、devtoolのconsole出力が静かになるまで待つ
これは1回cacheに入ればよいshokai.icon
3分ぐらいかかる
リロードする
これで準備完了!
負荷をかける
以下の1〜3を繰り返すと、out of memoryが発生する
1. IMEオフにして、#aaaaabbbbbccccddddみたいなhashtagを素早く何度も変更する
キーボードをガチャガチャ打ったり、backspaceキーを何度も押したり
これをやると、page.linksが更新されて、サーバーに保存され、socket.ioでlinks changeが送られてきて、QuickSearchの辞書再作成が何度もWorkerに依頼される 2. カーソルをリンク記法がある行に上下から何度も侵入・離脱を繰り返す
特に3が効くかもしれない。1と2の要素も含んでいるのでshokai.icon
https://gyazo.com/0332df808bd8ce67544fb93df7d89464
改善したらだんだん長生きするようになっていった
最新の100万ページぶんのpage titles APIのfetchが完了するまで耐えられるようになって
そのまま編集し続けられるようになった
クラッシュした箇所がDevToolsで見れるの知りませんでした…!有益情報だteramotodaiki.icon
まだクラッシュはしていません。クラッシュしそうな雰囲気を検知して、クラッシュ前に止まりますshokai.icon
以下、検出したout of memoryとその解決方法のメモ
100万ページを編集してると、mergeChunksToMessageでout of memoryが検出されたshokai.icon https://gyazo.com/412e2c9a86f4510454d788483c699ea8
変更
mergeChunksToMessageとsplitMessageToChunksをasync関数化した
今度はWorker内で使ってるlodashのlodash.uniqByでout of memoryが検出された https://gyazo.com/e9f373732e8e84e81b1159b7cec37479
uniqByと同等の処理を自作した
クソデカ配列対策として、1000件おきにawait delay(1)を挟むようにした まだmergeChunksToMessageがダメらしい
https://gyazo.com/a01f9477ea6746994a1b5f55edd72992
objectの全keyとプロパティの配列を作るので
デカいobjectでやると、デカい新規Arrayができる?
ちゃんと参照渡しになってるから問題なさそうだ
code:js
$ node
for (const key, value of Object.entries(o)) { value.shift() } 1
o
でもなんとなくfor inで書き直した。勢いでやったshokai.icon
msgObj[key] = msgObj[key].concat(value)は新規のArrayを作ってて怪しい
msgObj[key].push(...value)に書き直した
こっちは効いてそうshokai.icon
5分ぐらいずっと負荷をかけ続けていたら、for (const page of [..._pages, ...links])でout of memory発生
https://gyazo.com/61a8e5be4d2edcc05a0ae9e5411378de
全要素がコピーされた新規Arrayが作られる
これはブラウザ側がステップ実行状態にならなかった
Workerの中だから当然か
あと一歩という手応えがでてきたshokai.icon
修正
code:js
for (const page of arr) {
spread operatorで連結する必要なんて全く無かった
上の変更をぜんぶやった結果、out of memoryが発生しなくなったshokai.icon
負けた。7分ぐらいずっと負荷かけてたらクラッシュした
https://gyazo.com/c01bc6862bf6650f004a0ffb8fbf47f8
Chrome devtoolsもout of memoryの可能性を検出できず、いきなり死んだ
まあ、最初の頃よりはだいぶマシになったのは確かだshokai.icon
学んだ事
デカいループはたまにawait delay(1)いれろ
lodash.uniqByやめろ
とにかく新規のArray作るのやめろ使いまわせ