60MBの静的なJSONにフロントエンドのみで立ち向かったお話
ある日起きた困った出来事
はい、こんにちは。安立です。
先日、静的に保持していた約5MBのJSONファイルが、更新が入り10倍以上の60MBになって困ってしまうと言う出来事が起きました。
どうにかこうにか、フロントエンド(JavaScript)のみで立ち向かった・・・そんな経験を書いていきます。
前提
- Vue.jsで作っています。
- JSON読み込んでオブジェクトに格納するところまでとなります。実際にはその後も色々やっているのですが、細かすぎる話になるので省きます。
- この記事では具体的なコードは書いていないです。こうやったら改善されたよという手順のみです。gzipのJavaScriptでの解凍方法や、WebWorkerの使い方など。その辺りは調べるといくらでも出てくるので調べましょう。(気が向いたら別記事で書くかもしれません。)
考えた対応策
そもそものデータをバックエンドで管理する事や、JSONの構造を変更してデータ容量減らす事など根本的な対応策も考えられますが、色々事情もあり今回はフロントエンドで完結できる対応策を考える事になりました。
そこで考えた対応策としては以下2点です。
- JSONをgzip化する
- 重めの処理をWebWorkerを使い別スレッドで処理する
JSONをgzip化する
ページにアクセスする度に60MBのデータをダウンロードっていうのは、エンドユーザーにとって嫌がらせでしかないです。
そのためJSONをgzip化してデータ量を減らします。
ちなみにgzip化することで、2.5MB程になります。素敵ですね。
重めの処理をworkerを使い別スレッドで処理する
JSONのデータ量が膨大のため、JavaScriptでそのまま処理してしまうとページのレンダリングに多大な影響があります。
具体的にいうと、ページのローディングにアニメーションを使っているのですが、JSONのデータを処理している間アニメーションが止まってしまい、バグに見てしまったり・・・ですね。
そのため、負荷が掛かる処理をWebWorkerを使いマルチスレッド化することで、メインスレッドの処理に影響を与えないようにと考えました。
実行した内容
- JSONをgzip化
- gzipをjavascriptで解凍する処理を書く
- 2をWorkerでの処理に変更
- ストアに持っていたデータを一部グローバルに移行(※)
※大量のデータをストアに格納する処理がとてつもなく重く、読み取りのみ必要なデータはグローバルオブジェクトに移行しました。ちなみに、Vueのdataプロパティに格納も重かったです。
(結果的に、gzipやWebWorker処理とかよりも効果が高かったのは内緒です。)
結果
以下に、実行した内容をもとに、処理速度を計測したデータを書いておきます。
結論から言うと大勝利です!!!
表の前提
- 単位はmsです。
- それぞれの処理で10回試しての平均値を出しています。
以下は、うまく表見出しに収めるだけの言葉にすることができなかたっため、それぞれのNo.が何に対応しているかの凡例です。
- No.1:元の処理
- No.2:JSONをgzip化し、JavaScriptで解凍する
- No.3:No.2の処理をWebWorkerでやる
- No.4:No.3に加えストアではなくdataプロパティに代入
- No.5:No.4をdataプロパティではなくグローバルのオブジェクトに代入
回数 | No.1 | No.2 | No.3 | No.4 | No.5 |
---|---|---|---|---|---|
1 | 10,070 | 12,725 | 8,111 | 8,076 | 2,973 |
2 | 10,077 | 8,695 | 7,850 | 7,897 | 2,996 |
3 | 9,815 | 8,833 | 7,317 | 7,909 | 2,977 |
4 | 8,615 | 12,159 | 7,872 | 6,523 | 3,049 |
5 | 12,602 | 9,017 | 7,620 | 6,830 | 2,796 |
6 | 10,350 | 12,620 | 7,823 | 6,438 | 2,798 |
7 | 10,333 | 11,696 | 7,850 | 6,795 | 2,717 |
8 | 13,340 | 12,919 | 7,932 | 6,492 | 2,865 |
9 | 9,515 | 8,635 | 8,159 | 6,926 | 3,172 |
10 | 9,572 | 8,414 | 7,918 | 7,082 | 2,595 |
平均値 | 10,070 | 10,571 | 7,845 | 7,097 | 2,894 |
JSONを読み込んでJavaScriptのオブジェクトに格納するところまでの処理は、7,200ms程短縮(約72%削減!)できました。
最初はどうなる事かと思いましたが、どうにかOKなレベルにできましたね。
実際はこの後に、大量のデータを検索する重めの処理は別途WebWorkerの処理にするなど、まだまだやった事は色々あったりします。
いや〜、それにしてもJavaScriptだけでも色々やりようのある時代になりましたね。
楽しいですね。
皆様も良いWebフロントエンドライフをお過ごしください。
さよなら〜👋
Discussion