Slide 1

Slide 1 text

画像のバリデーションは
 ファイルサイズチェックだけでいいと思って ない?
 株式会社ラクーンホールディングス
 yamashita.kiyoshi(@ky6yk)


Slide 2

Slide 2 text

まずは自己紹介
 名前:山下 清史
 所属:株式会社ラクーンホールディングス 技術戦略部 開発チーム
 主な仕事:BtoB卸売りサイト スーパーデリバリーの開発
 興味のある技術:Java, Spring


Slide 3

Slide 3 text

もくじ - 画像を処理するときに発生する問題の解決を任された
 - 画像のバリデーションには落とし穴があった
 - 画像編集処理時のメモリ使用量を調べてみた!
 - どうやってメモリ使用量を抑えるか
 - まとめ


Slide 4

Slide 4 text

ユーザーが任意の画像をアップロードできる機能で
 Out Of Memoryエラーが発生した
 
 「メモリ不足を避けるために、画像アップロード時のバリデーションを追加する」
 というタスクを任された
 画像を処理するときに発生する問題の解決を任された


Slide 5

Slide 5 text

画像を処理するときに発生する問題の解決を任された
 


Slide 6

Slide 6 text

ユーザーが任意の画像をアップロードできる機能で
 Out Of Memoryエラーが発生しました
 
 「メモリ不足を避けるために、画像アップロード時のバリデーションを追加する」
 というタスクを任されました
 画像を処理するときに発生する問題の解決を任された


Slide 7

Slide 7 text

Out Of Memoryを防ぐために、ファイルサイズが大きい画像はアップロードできないよう に実装しました
 これでOKかと思いきや・・・
 画像を処理するときに発生する問題の解決を任された
 
 


Slide 8

Slide 8 text

初耳でした…
 本当にそうなのか勉強も兼ねて検証してみました
 (一部抜粋)
 OOM が発生する巨大な画像は
 ファイルサイズに依存していない可能性があります。 画像のバリデーションには落とし穴があった つよつよエンジニアからの指摘

Slide 9

Slide 9 text

画像編集処理時のメモリ使用量を調べてみた!
 - 7000×7000のPNGファイル(6.1KB)を70×70にリサイズ 
 - 4032×3024の先輩のネコ画像( 11.7MB)も同様にリサイズ
 - Goのtestingパッケージ内に含まれているベンチマークを取得する仕組みで 
 平均メモリ使用量を確認
 7000×7000のPNGファイル(6.1KB) 4032×3024の先輩のネコ(11.7MB)

Slide 10

Slide 10 text

画像を70x70にリサイズするときの平均メモリ使用量
 結果


Slide 11

Slide 11 text

ファイルサイズよりメモリ使用量が高いのはなぜ? - メモリ使用量はファイルサイズではなく解像度に左右されます
 - 画像をメモリに展開するときの
 メモリ使用量は基本的に下記のような式で見積もれます
 画像のデータ量 = 横ピクセル数 × 縦ピクセル数 × 1ピクセルの情報量
 


Slide 12

Slide 12 text

ファイルサイズよりメモリ使用量が高いのはなぜ? 
 ファイルサイズがどれだけ小さくても、高解像度の画像であれば
 メモリに展開したときに使われるメモリは多くなります
 
 
 つまり、画像をメモリに全部展開する前に
 縦横ピクセル数でバリデーションする必要があります


Slide 13

Slide 13 text

JPEG、 PNGでは画像の縦横ピクセル数はヘッダ情報に載っています
 画像を展開する前に縦横ピクセル数(解像度)が取得できるのでは?
 調べてみました!
 どうやってメモリ使用量を抑えるか


Slide 14

Slide 14 text

- コードで、7000×7000のPNGファイル(7KB)のヘッダ情報から
 縦横ピクセル数を取得
 - Goのtestingパッケージのベンチマークを取得する仕組みで
 平均メモリ使用量を確認
 どうやってメモリ使用量を抑えるか


Slide 15

Slide 15 text

結果 メモリ使用量は平均215Bで済みました 
 少ないメモリ使用量で縦横ピクセルを取得できました 
 
 
 BenchmarkReadPngHeader-8 100 639716 ns/op 215 B/op 4 allocs/op 1回の平均メモリ使用量

Slide 16

Slide 16 text

まとめ - サーバーサイドでの画像編集はメモリ使用量が高い操作
 - 処理される画像データはメモリ上に縦横ピクセル分展開されるため
 - サーバー上でのメモリ不足の発生を避けるために画像のヘッダ情報を使って
 メモリ使用量を見積り、事前に処理を停止するなどの判断ができる


Slide 17

Slide 17 text

ありがとうございました!!
 サンプルコードが載っているブログ🦝