Slide 1

Slide 1 text

multipart/form-dataの省メモリパース Go Conference 2024 Pre Party @mazrean

Slide 2

Slide 2 text

mazrean 2 ◼東工大 修士2年 ⚫traP所属 ◼Goでライブラリ等を作っている ⚫GenORM[1]:Genericsを使ったSQL Builder ⚫FormStream[2]:multipart/form-dataの省メモリパーサー 今日はこれの話 [1]: https://github.com/mazrean/genorm [2]: https://github.com/mazrean/formstream

Slide 3

Slide 3 text

multipart/form-dataとは? 3 ◼フォームデータの送信に使うContent-type ⚫ファイルアップロードによく使われる ◼フィールドに対応したPartの境界文字列区切り ◼Partの順番が維持されるとは限らない[3] [3]: https://datatracker.ietf.org/doc/html/rfc7578#section-5.2

Slide 4

Slide 4 text

Goでのmultipart/form-dataのパース 4 ◼標準のmime/multipartパッケージでパースできる ◼2種類のパース方法が用意されている ⚫(*Reader).NextPart ⚫(*Reader).ReadForm

Slide 5

Slide 5 text

(*Reader).NextPart 5 ◼Partを前から順に読み込む ◼ ストリーム処理によりメモリ効率が良い ◼ Partの順番が変わった際の対応が困難 ⚫例: iconを含めたユーザー情報の保存   前から 取り出し

Slide 6

Slide 6 text

(*Reader).ReadForm 6 ◼リクエスト全体をメモリ・ディスクに読み込む ◼ Partの順番が変わった際の影響なし ◼ メモリ効率が低い  

Slide 7

Slide 7 text

理想的なmultipart/form-dataのパース 7 ◼Partの順序に関わらず処理できる ◼ファイルPartを極力ストリーム処理したい FormStream

Slide 8

Slide 8 text

FormStream 8 ファイルPartの処理を工夫 ◼必要なPartが全て前に存在(FastPath) → ストリーム処理 ◼必要なPartがそろっていない(SlowPath) →メモリまたはディスクに一時保存 FastPath SlowPath

Slide 9

Slide 9 text

ベンチマーク:メモリ使用量 9 ◼FastPathでReadFormと比べて桁違いに少ない ◼SlowPathでもReadForm以下

Slide 10

Slide 10 text

ベンチマーク:実行時間 10 ◼FastPathはReadFormの半分以下 ◼SlowPathでもReadForm以下

Slide 11

Slide 11 text

まとめ 11 ◼multipart/form-dataはPartの順序が不定 ◼mime/multipartでは効率的なパースが難しい ◼multipart/form-dataパーサーFormStreamを作った ⚫ReadFormと比べメモリ使用量大幅減 ⚫Partの順序入れ替わりに対応