WebPは本当に最速なのか？！

# はじめに
こんにちは。みんなのウェディングの合原です。
この記事はくふうカンパニーアドベントカレンダー13日目になります。
今回は、実用され始めてきているWebPが、AWSのCloudFrontやnginxを利用した静的ファイル配信とで比較した場合でどれだけ差があるのか気になったので、検証してみました。

※自前で用意した`webp`画像および生成元となる`jpg`画像それぞれを複数枚、以下のパターンでロードし、実際の読み込み完了までの時間を計測し、比較してみました。

# WebPとは？
一応おさらいを少し。
> [2010年9月30日に仕様が公表され、各種ツールと共に提供が開始され](https://ja.wikipedia.org/wiki/WebP#OS)

Googleが開発した新しい画像フォーマット。具体的には、
> インターネットのWebページで広く使われている非可逆圧縮のJPEGや可逆圧縮のGIF、PNGの置き換えを意図する規格

であるため、多量あるいは大量の画像配信に置いて、転送量軽減により、表示速度の大幅な高速化が期待できます。

# 検証環境

```sh
Rails 5.2.1
Ruby 2.5.1
```

## 画像配信パターン
以下のパターンにて検証。

1. オリジンとしてS3に静的ホスティングした`jpg`画像を、 CloudFront経由で配信
1. オリジンとしてS3に静的ホスティングした`webp`画像を、 CloudFront経由で配信
1. オリジンとしてS3に静的ホスティングした`webp`画像を、 カスタムオリジン設定した画像配信（用の）サーバ（nginx）を経由して配信

※上記のAWSサービスのそれぞれの設定等については割愛

## 計測
主に次の２点。

### 画像自体のダウンロード時間に差異はないか？
* curl（こちらは画像自体のダウンロード時間） * 30

### 複数枚になった場合、ダウンロード時間の差異はどうなるのか？
* curl（こちらは画面内のコンテンツ全てのダウンロード時間） * 30

以上の2つ。
※クライアント側でのレンダリングについても検証したかったのですが、今回は時間の都合上割愛しました :confounded:  。

> １画面にロードする画像枚数

を変化させながら検証する。
※ブラウザのキャッシュはもちろん, `disable　`にて。

### １画面にロードする画像枚数
`10, 30,　50`の3パターンで表示枚数を変えながら検証

> 例

```haml
- 10.times do
  -# 下記の３パターンそれぞれで検証していきます
  -# = image_tag "/image/32/2.jpg", width: "100%", class: "img-responsive"
  = image_tag "/image/32/2.webp", width: "100%", class: "img-responsive"
  -# = image_tag "/crop/920x651/image/32/2.jpg", width: "100%", class: "img-responsive"

```


# 検証１
## 画像自体のダウンロード時間
### オリジンとしてS3に静的ホスティングした`jpg`画像を、 CloudFront経由で配信
| download |
|-----------:|
| 0.365824 |
| 0.317291 |
| 0.349641 |
| 0.317291 |
| 0.349641 |
|:|
| 0.3681076667 |

平均： `0.3681076667`
※ms

### オリジンとしてS3に静的ホスティングした`webp`画像を、 CloudFront経由で配信
| download |
|-----------:|
| 0.286072 |
|--:|
| 0.306347 |
|--:|
| 0.248396 |
| 0.286629 |
| 0.290034 |
| 0.289651 |
| 0.28523 |
| 0.319361 |
| 0.290087 |
|:|
| 0.300071 |

平均： `0.300071`
※ms

### オリジンとしてS3に静的ホスティングした`webp`画像を、 カスタムオリジン設定した画像配信（用の）サーバ（nginx）を経由して配信
| download |
|-----------:|
| 0.286072 |
| 0.291394 |
| 0.307719 |
| 0.30992 |
| 0.296628 |
| 0.287113 |
| 0.298628 |
|:|
| 0.3044494333 |

平均： `0.3044494333`
※ms

# 検証2（特定の複数枚の画像を配置したページをロードする）
## １画面に画像10枚の場合
### オリジンとしてS3に静的ホスティングした`jpg`画像を、 CloudFront経由で配信
```sh
$ for i in `seq 30` ; do curl 'http://localhost:3000/test/32/' -H .. --compressed -s -o /dev/null -w "%{time_starttransfer} \n"; done;
0.287672 
0.229243 
0.214527 
0.202688 
0.231664 
0.201712 
0.201133 
0.155635 
0.197781 
0.196832 
0.219549 
0.182356 
0.218925 
0.252057 
0.195242 
0.193347 
0.231018 
0.170652 
0.210965 
0.200060 
0.209175 
0.161397 
0.180013 
0.212429 
0.171338 
0.164466 
0.189398 
0.240789 
0.187352 
0.180264

average 0.2029893
````

## オリジンとしてS3に静的ホスティングした`webp`画像を、 CloudFront経由で配信
```sh
$ for i in `seq 30` ; do curl 'http://localhost:3000/test/32/' .. -w "%{time_starttransfer} \n"; done;
0.171939 
0.183526 
0.181000 
0.164860 
0.212650 
0.193401 
0.184867 
0.198148 
0.212202 
0.174958 
0.174259 
0.213074 
0.177883 
0.181077 
0.203633 
0.203474 
0.206115 
0.245013 
0.200903 
0.210618 
0.232621 
0.187968 
0.173155 
0.192243 
0.188722 
0.209217 
0.210133 
0.173706 
0.188923 
0.166086

average 0.1920578667
````

## オリジンとしてS3に静的ホスティングした`jpg`画像を、 カスタムオリジン設定した画像配信（用の）サーバ（nginx）を経由して配信
```sh
$ for i in `seq 30` ; do curl 'http://localhost:3000/test/32/' -H 'Connection: keep-alive' ..
0.215563 
0.205946 
0.210164 
0.226714 
0.180904 
0.209132 
0.177263 
0.174463 
0.163805 
0.175217 
0.175343 
0.148664 
0.205492 
0.202289 
0.162958 
0.199378 
0.194599 
0.150650 
0.157925 
0.199585 
0.167494 
0.156616 
0.169303 
0.219654 
0.172360 
0.195761 
0.175937 
0.191682 
0.167754 
0.154522

average 0.1835712333
````

## １画面に画像30枚の場合
### オリジンとしてS3に静的ホスティングした`jpg`画像を、 CloudFront経由で配信
```sh
$ for i in `seq 30` ; do curl 'http://localhost:3000/test/32/' -H .. --compressed -s -o /dev/null -w "%{time_starttransfer} \n"; done;
0.209697 
0.202030 
:
average 0.1986107333
````


## オリジンとしてS3に静的ホスティングした`webp`画像を、 CloudFront経由で配信
```sh
$ for i in `seq 30` ; do curl 'http://localhost:3000/test/32/' -H .. --compressed -s -o /dev/null -w "%{time_starttransfer} \n"; done;
0.209697 
0.202030 
:
average 0.1907079667
````

## オリジンとしてS3に静的ホスティングした`jpg`画像を、 カスタムオリジン設定した画像配信（用の）サーバ（nginx）を経由して配信
```sh
$ for i in `seq 30` ; do curl 'http://localhost:3000/test/32/' -H .. --compressed -s -o /dev/null -w "%{time_starttransfer} \n"; done;
0.209697 
0.202030 
:
average 0.1828506667
````

## １画面に画像50枚の場合
### オリジンとしてS3に静的ホスティングした`jpg`画像を、 CloudFront経由で配信
```sh
$ for i in `seq 30` ; do curl 'http://localhost:3000/test/32/' -H .. --compressed -s -o /dev/null -w "%{time_starttransfer} \n"; done;
0.237864 
0.177258
:
average 0.2008491333
````
## オリジンとしてS3に静的ホスティングした`webp`画像を、 CloudFront経由で配信
```sh
$ for i in `seq 30` ; do curl 'http://localhost:3000/test/32/' -H .. --compressed -s -o /dev/null -w "%{time_starttransfer} \n"; done;
0.209697 
0.202030 
:
average 0.1916496667
````

```sh
$ for i in `seq 30` ; do curl 'http://localhost:3000/test/32/' -H .. --compressed -s -o /dev/null -w "%{time_starttransfer} \n"; done;
0.209697 
0.202030 
:
average 0.1848868
````


## オリジンとしてS3に静的ホスティングした`jpg`画像を、 カスタムオリジン設定した画像配信（用の）サーバ（nginx）を経由して配信
```sh
$ for i in `seq 30` ; do curl 'http://localhost:3000/test/32/' -H .. --compressed -s -o /dev/null -w "%{time_starttransfer} \n"; done;
0.149494
0.178389
:
average 0.1794062667
````

# 結果
## 画像単体のダウンロード時間
webp自体は確かに軽量化された画像ゆえに、従来の画像フォーマットよりは転送量を抑えられています。
一方で、CDN上の画像サーバ経由の画像と比較するとダウンロード時間に大きな差は見られないとも言える結果になしました。

## 複数枚になった場合、ダウンロード時間の差異はどうなるのか？
こちらはむしろ、CDN上画像配信用サーバ経由の画像配信の方が速い結果となりました。
大きくはキャッシュの恩恵が大きく、`webp`によるそもそもの軽量化を凌ぐ結果となったと考えられます。

## 結果からの考察
1. 必ずしも、webpにしたからと言って高速化が図れるわけではない
1. webpの圧縮率は従来の形式に比べかなり効率的なため転送量の削減では効果が期待できる
1. コスト面では、効率的な画像サイズの圧縮により、転送量の削減もできるため、使用するCDNサービス等の課金形態によってはコストメリットもあるかもしれません。

webpを採用するか否か、今回の検証だけで考えると、CDNやその他のキャッシュ機構が潤沢に使える環境下では必要がないかもしれません。また、深くは触れていませんが、現状まだ、非サポートのブラウザもあるので、この点も踏まえ導入する必要があります。

個人的にはWebPを積極的に使っていきたいですが、十分な検討が必要なため、みんなのウェディングで採用できるときがきましたら、また[レポート](https://blog.mwed.info/)させていただきます。

[くふうカンパニーアドベントカレンダー](https://qiita.com/advent-calendar/2018/kufu)、14日目となる明日は[kiyokuro](https://qiita.com/kiyokuro)さんです!どうぞご期待ください！