Upgrade to Pro — share decks privately, control downloads, hide ads and more …

その処理、本当に遅いですか? 〜無駄を削る達人になろう〜

その処理、本当に遅いですか? 〜無駄を削る達人になろう〜

その処理、本当に遅いですか? 〜無駄を削る達人になろう〜

More Decks by レバレジーズTechアカウント

Other Decks in Technology

Transcript

  1. 自己紹介 桐生直輝 (23歳) • 入社:2023年3月 • 出身:岡山県津山市 • 所属:HRテック事業部 ◦

    バックエンド〜インフラ担当 • 趣味:コンピュータいじり、自宅サーバー構築 • 目標は技術力でとことん尖ることです
  2. 「無駄」を感じ取るには 何をするのにどれくらいの時間がかかるか、感覚を掴む • 例えば、現代のCPUがどのくらい高速か知っているでしょうか? 例:CPU vs ストレージ vs ネットワークアクセス 1秒あたりの処理能力比較

    (目安) 3,000,000,000 IPS 1,000,000 IOPS 1,000 RPS 1回のネットワーク通信の完了を待つ間に、 SSDは1000回の読み書きを実行でき、 CPUは300万回の計算を実行できる。 ※並列度=1
  3. 「無駄」を感じ取るには 処理時間を概算してみる • 例:100ユーザーで、各ユーザー1000件程度のデータを集計する(合計・平均など) ◦ トータルの処理件数は 100 * 1000 =

    10万件程度 ◦ 単純な集計なら1件あたり数十ステップで処理可能 →実時間では数ミリ秒程度 ◦ DBからのデータの取得も 10万件程度なら最大で数秒程度しかかからないはず • ここで概算した時間(数秒)を大きく上回る場合、無駄が存在することになる
  4. 計測の手法 経過時間を計測し、ログ出力 • ポイントごとの時刻を記録し、その差分から処理時間を算出する function run() { const startTime =

    new Date(); // new Date() は現在の時刻を取得する const data = getData(); const afterGetDataTime = new Date(); const transformed = transformData(data); const afterTransformTime = new Date(); saveData(transformed); const afterSaveDataTime = new Date(); console.log(‘getData():’, afterGetDataTime - startTime, ‘ms’); console.log(‘transformData():’, afterTransformTime - afterGetDataTime, ‘ms’); console.log(‘saveData():’, afterSaveDataTime - afterTransformTime, ‘ms’); }
  5. 高速化の実施 例:月次の勤怠締め操作 (給与計算ソフト) • 1ヶ月分の勤怠データを締めて給与額を算出する処理 • 300人分のデータで7分以上かかる • 処理量が多いためであると諦められていたが、計算内容と処理時間が乖離していると感じ 高速化に着手

    ◦ 300人 * 30日 = 9000個の勤怠データの集計 + 過去の有給使用データ (300人 * 数十件 = 数 千〜1万件) の集計 ◦ データの取得等含めて考えても何十秒もかかるのですらおかしい
  6. 高速化の実施 1ユーザーごとに多数のクエリを発行していた • ループ内でクエリを発行していた &同じデータを何回も取ってきていた ◦ 何万回ものクエリ発行 ◦ ネットワーク通信待ち +

    クエリ実行のオーバーヘッドで結構時間を取られる • 全ユーザーのデータを予め一括で取得するようにして解決 ◦ 1件SELECTを10000回やるより10000件SELECTを1回の方が圧倒的に速い
  7. 高速化の実施 例2:TypeORM マイグレーションの高速化 • マイグレーション = DBスキーマ変更クエリの実行 • マイグレーションコマンドが立ち上がるまでに 10分弱かかっていた

    • どう考えても時間のかかり方が異常で、無駄がありそう ◦ ただマイグレーションのクエリ実行を準備するのに 10分もかからないはずなので
  8. 高速化の実施 TypeScriptのコンパイルがそんなに重いはずがない • 確かにtsファイル数は多い(2000ファイル弱) • しかし、プロジェクトのビルド(npm run build)には10秒くらいしかかからない • 仮説:

    ts-nodeが1ファイルずつビルドしているのでオーバーヘッドが大きく、重い? ◦ 同じファイルを何度もコンパイルしている可能性?