はじめに

前回の記事では、ChatGPTを活用してWebアプリ「Test Scorer – テスト自動採点アプリ」を開発した時の流れをご紹介しました。その記事の最後にも書きましたが、このアプリには「新規テスト作成時の設問数が増えると、次画面への遷移に時間がかかってしまう」というパフォーマンス上の問題がありました。
この記事では、

  • どのようにパフォーマンスを改善したか
  • どれだけパフォーマンスが改善されたか

についてまとめます。

修正前のコード

こちらは修正前のコードです。処理の流れは以下の通りとなっています。

  1. ユーザごとにドキュメントを作成します。(1行目)
  2. その中にテストの基本情報をセットします。(4行目〜8行目)
  3. 最後に設問数分のドキュメントを作成します。(12行目〜16行目)
Dart
final problemRef = FirebaseFirestore.instance.collection(user.uid).doc();

// テスト名・設問数・作成日時を保存
await problemRef.set({
  'name': name,
  'creation_date': DateTime.now(),
  'isAnswering': false,
});

// 設問数分のドキュメントを作成
if (numValue != null) {
  for (int i = 0; i < numValue; i++) {
    await problemRef
        .collection('correct_answer')
        .add({'index': i, 'answer': ''});
  }
}

このコードでは、設問数分だけawaitを使用して個別にFirestoreへの書き込みを行っている(12〜16行目)ため、書き込み回数が増えるとパフォーマンスが低下してしまいます。

どのようにパフォーマンスを改善したか

Firestoreのバッチ書き込みを使用することで、一度に複数の書き込みを行うようにします。これによりFIrestoreへの書き込み回数が最小限に抑えられるため、パフォーマンスを向上させることができます。

修正後のコード

修正後のコードがこちらです。

Dart
final problemRef = FirebaseFirestore.instance.collection(user.uid).doc();
final batch = FirebaseFirestore.instance.batch();

// テスト名・設問数・作成日時を保存
batch.set(problemRef, {
  'name': name,
  'creation_date': DateTime.now(),
  'isAnswering': false,
});

// 設問数分のドキュメントを作成
if (numValue != null) {
  for (int i = 0; i < numValue; i++) {
    final answerRef = problemRef.collection('correct_answer').doc();
    batch.set(answerRef, {'index': i, 'answer': ''});
  }
}

// バッチ書き込みを実行
await batch.commit();

このコードでは始めにバッチを作成(2行目)し、それに対してset()オペレーションで値を設定(15行目)しています。そして最後に1度だけcommit()オペレーションを実行(20行目)し、Firestoreにデータの書き込みを行っています。

どれだけパフォーマンスが向上したか

ローカル環境のデバッグモードにおいて、設問数200個のテストを作成した際の処理時間を測定しました。

#修正前 [ms]修正後 [ms]
18254263
27132264
37043284
47375278
57240330
平均値7408.8283.8

単純計算で約26倍のパフォーマンス向上となりました。
設問数1000個のテストを作成した場合でも2秒程度の処理時間となったため、このパフォーマンスであればこれまで最大200個としていた設問数の制限を緩和できそうです。

さいごに

Firestoreで複数のドキュメントを書き込む際には、バッチ書き込みを活用することでパフォーマンスを向上させられることがわかりました。
このブログ記事が、Firestoreを使ったアプリケーションのパフォーマンス向上に役立つことを願っています。
記事の内容についてもっと詳しく知りたいことや気になることがあれば、コメントいただけると嬉しいです。

X(旧Twitter)で記事の更新をつぶやいていますので、フォローよろしくお願いします!