Javascriptのreduceを使い倒した結果、シンプルなループになった

365 Views

April 25, 24

スライド概要

profile-image

技術支援をしています。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

Javascriptのreduceを 使い倒した結果、シンプ ルなループになった 2024/04/25 merutin

2.

merutin 公官庁向けシステム開発 → ERPパッケージベンダー → DELTA 特定の技術にこだわらず、お客さんに合わせて何でもやっています。 直近1年くらいの仕事 ● ● ● ● ● Ruby on Railsの一部を切り出して、Lambda + DynamoDBに変更 Next.js + Go + Keycloakで認証認可のPoC作成 AWS、Google Cloudコスト削減 Firestoreのリアーキテクチャ 社内の管理会計ソフトウェアの開発

3.

社内の管理会計ソフトウェア(DASH) DELTAが所属しているSEVENRICH GROUPでは会計をメインとして、様々な事業 が存在しています。 DASHは各事業ごとのPLを登録・閲覧するためのツールとして利用しています。 AWS上で動作しており、Lambda、DynamoDB、SQS、API Gatewayを利用していま す。 - 言語:TypeScript フロントエンド:Next.js バックエンド:Apollo Server API:GraphQL

4.

管理会計を管理するソフトウェア(DASH) DASHでは部門(全社 -> xx事業 -> xx店舗)単位での入力を行います。 部門の親として事業があります。事業の数値は部門の合算値としています。 事業の合算として、全社のデータがあります。 SEVENRICH GROUPでは100近い部門が存在しており、勘定科目の親項目(販管 費 -> 人件費)の計算等もあるため、全社のデータを計算するとなると、結構な量の データになります。 ※ 1年分のデータで80000件

5.

Javascriptにおける配列処理 配列はforでループを処理することが一般的でしたが、filter、map、reduce等のメ ソッドが追加されて以降は、これらの関数型っぽい処理を書く事が多いかと思いま す。今回はreduceに焦点を当てます。

6.

reduce概要 1から100までの数値を合計する処理を書くとこんな感じになります。 reduceのほうがシンプルにかけるかつ、constな値しかないので、意図しない修正 が発生しにくいので、個人的には良く使っています。

7.

DASHでの利用方法 DASHでは前述のように、子部門 → 事業 → 全社のような計算が必要になるため、 reduceを多様して、処理を行っていまし た。 実際には孫部門も許可する作りになって いたり、勘定科目ごとの合計が入ったりす るので、もうちょっと複雑です。

8.

DASHでの利用方法 初期のDASHでは、勘定科目が最低限のの入力だったため、何とか動作していた のですが、運用変更に伴い、勘定科目が激増しました(10 → 60)。 データ量が単純に6倍になった結果、集計処理が非常に重くなり全社の合計を出 すのに数分かかる処理になっていました。 Lambdaの実行ログ。429秒 = 7分ちょい Duration: 429450.95 ms Billed Duration: 429451 ms Memory Size: 4096 MB Max Memory Used: 1183 MB Init Duration: 410.95 ms

9.

reduceを調べる 一方で、関数を利用した場合は処理が遅くなることが知られています。 https://qiita.com/sg0hsmt/items/85dc1857b259ce7f2b25

10.

reduceを調べる reduceはループのたびにObjectを作り直ししているため、下記の例だとpreに該当 するオブジェクトが100回生成されているようです。 例では数値のため、それほど生成のコストは大きくないと思われますが、DASHで は複数の値が入ったObjectを回していました。

11.

試しに、一部の配列をforにしてみた 別の機能改修が入ったときに処理がさらに遅くなったため、試しに一部のreduceを forに変更してみました。

12.

reduceをほぼやめてみた結果 Before: Duration: 429450.95 ms Billed Duration: 429451 ms Memory Size: 4096 MB Max Memory Used: 1183 MB Init Duration: 410.95 ms After: Duration: 1053.06 ms Billed Duration: 1054 ms Memory Size: 4096 MB Max Memory Used: 168 MB Init Duration: 443.23 ms 数百秒かかっていた処理が1秒以内に終わるようになった!!!

13.

まとめ - Arrayのメソッドは関数型っぽく記述できるので便利だけど、ある程度複雑な処 理にだと速度的には向かない 特にmapやreduceといった、元のObjectを作り替える系の処理はめっちゃ速 度に影響出るので、利用する時はパフォーマンスを気にしたほうが良い