API化したGASの高速化まとめ
ひょんな事から、GAS経由でスプレッドシートの中身をAPI化する案件を頂き、ざっと構築したのは良いがあまりにも処理が遅すぎたので、高速化のためにやったあれやこれをまとめる。
全データ取得
まず、一番の高速化と言えば、データ取得。 for文で回してセルのデータを取るのではなく、
Sheets.Spreadsheets.Values.batchGet(sheetId, request).valueRanges
みたいな感じで、ぐわっとデータを取るのが早い。 これは以前にやった事がある事だったので、基本中の基本なのだが、これだけだと高速化しなかった。
キャッシュ化
今回の案件は、複数のスプレッドシートからデータを取得して表示するという物であった。
故に、初回の実行時はどうしても何度かリクエストを飛ばす必要があった。
で、これが同じネットワーク(?)内だとある程度キャッシュが効くのだが、別のネットワークになると途端に起動が重くなるというクソ仕様現象が生じた。
これを解決するために、色々調べた結果、CacheServiceを使うと良い事が分かった。
const cache = CacheService.getUserCache();
みたいにして、後は
let data = cache.get("keyName");
if( !data ){
//dataを色々処理
cache.put("keyName",JSON.stringify(data));
}
と書いて対応する形にした。 今回は、APIを起動実行するユーザが一人しかいない前提なので、getUserCacheを採用したが、getDocumentCacheや、getScriptCacheとかでも全然構わない。
localStorageの採用
さらなる高速化として、localStorageを採用することにした。 これで、爆速化した。 一応、データ更新は3時間に1回という形にして、
let data = localStorage.getItem("keyName");
let dataObject;
// キャッシュ時間は3時間くらい
if( !data || data.expire < Date.now()){
//APIから取得処理
dataObject = fetch()
// expireをdataObjectに埋め込む
dataObject.expire = Date.now() + 10800000;
} else {
// ここで取得したデータをパースする
dataObject = JSON.parse(data);
}
// レンダリング処理
doRender(dataObject);
// save localStorage
localStorage.setItem("keyName", JSON.stringify(dataObject));
という感じにした。 実際にはもう少し複雑な事をさせてるが、概ね、この方向性で構築している。
高速化の結果
高速化の結果、初回起動10秒(一番最初のユーザ)は変わらないものの、2人目以降は2秒で初回データ読込、キャッシュ化されたら、0.5秒でデータ表示されるという所までチューニング出来た。 やばい(別にやばくない)。 当たり前の事なのだが、キャッシュ化はとてつもない速度アップに繋がる。 この辺をチューニング出来て本当に良かった。
まとめると
- 全データ一括処理
- CacheServiceを活用
- localStorageを活用
を適用するだけでかなりの高速化が可能になる。 今後、似たような仕事が舞い込んできた時には、この備忘録を参考にしたい。
コメント
コメントを投稿