35歳からの中二病エンジニア

社寺・鉄道・アニメを愛でるウェブ技術者の呟き

GDの画像圧縮率と処理速度

よくPHPのGDは重いと言われるが、重い中でも圧縮率の設定次第で大きくパフォーマンスが変わるという落とし穴にハマってしまったので、備忘録がてら綴っておきたい。

何が起こったのか

  • 商用サービスにおいて、アバターの合成・圧縮処理にGDの imagepng() 関数を使用していた。
  • 元々はデフォルトの圧縮率 6 だったのだが、ストレージの都合上アバターのサイズを抑えるため、圧縮率を最高の 9 に上げる事になった。
  • その後、アバター合成に使用しているサーバーの高負荷状態が頻発するようになったが、先の変更時には他にも各所変更が行われており、かつ時間も経過していたため、原因に気付けなかった。

どのように解決したか

  • 前置きすると、僕は高負荷状態が頻発するようになった後でサポートに入ったため、今回の問題は単にユーザー増加による負荷上昇だと認識していた。
  • 元々は画像合成専用のサーバーを新しく構築する方針だったが、GDの設定変更や他の画像処理エンジンを使う事で改善できないかと片手間で調べてみた。
  • すると、GDの圧縮率設定で大きくパフォーマンスが変わるという例が散見されたので、試してみると確かに大きく改善できた。
  • 詳細検証の上、商用サービス上に圧縮率 1 を適用すると、負荷は軽減された。

実際どの程度変わるのか

以下は、1.8MBのPNG形式画像に対し、imagepng() 関数を使用して1,000回連続で圧縮した結果である。

圧縮率 所要時間(s) 画像サイズ(byte)
0 28.009 1,846,883
1 31.094 285,950
2 31.165 283,031
3 32.331 279,795
4 38.613 268,360
5 40.412 267,109
6 44.709 266,506
7 49.050 266,224
8 83.864 265,515
9 198.975 264,067

これを見てわかる通り、圧縮率を 8 以上にすると一気に所要時間が増えていく。一方で圧縮後の画像サイズは 4 以上では大きく変わっていない。今回の問題で圧縮率を 6 から 9 にした事で高負荷状態が頻発するようになった事は、これで裏付けられた。

おわりに

GDの圧縮率設定は、8 以上にすると急激に所要時間が増える。上記のケースでは、所要時間と圧縮率のバランスを鑑みた場合、デフォルトの 6 付近で調整するのが妥当と言えるだろう。ただ、合成の手順や対象の画像によって結果が変わってくる可能性があるため、実際に使用するケースで上記のような検証を行った上で微調整するのが良いだろう。

ちなみに、先述の商用環境においては負荷は軽減されたものの、上記のケースのような劇的な効果は得られなかった。これは圧縮だけでなく、合成部分の負荷も合わさっているためと考えられる。合成部分の処理速度については今回は取り上げていないが、機会があれば検証してみたい。