HTTPのTransfer-Encoding: chunkedした時のデータの増量は0.0174%程度だった
#HTTP
知りたいこと
HTTPのTransfer-Encoding: chunkedした時に、元データと比べてどれぐらい増えるのかを知りたい。
Base64だとバイナリデータと比べて約133%増えるなどと言われていてそういった具合にTransfer-Encoding: chunkedの場合のデータの増加ぐあいを知りたい。(Base64 - Wikipedia)
検証方法
以下のようにサーバーをncコマンドで立てる。
code:bash
echo -e "HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 204 No Content\r\nContext-Length: 0\r\n\r\n" | nc -l 8282
以下のcurlがお行儀よくExpect: 100-continueしてくるので、データを受け取ったらレスポンスとして最初に100 Continueをして204 No Contentする。
以下のようにcurlコマンドでTransfer-Encoding: chunkedされるようにHTTPサーバーに送信する。
以下のようにするとPUTメソッドでseq 100の標準出力がHTTPのボディとして送信される。検証時はseqの代わりにあらかじめ用意した大きめのファイルをcatする。
code:bash
seq 100 | curl -T- localhost:8282
例: 以下はnc側(サーバー側)の出力例。この出力をリダクレクトして保存して大きさを測って元データからどれだけ増えるのかを調べる。
code:bash
$ echo -e "HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 204 No Content\r\nContext-Length: 0\r\n\r\n" | nc -l 8282
PUT / HTTP/1.1
Host: localhost:8282
User-Agent: curl/7.70.0
Accept: */*
Transfer-Encoding: chunked
Expect: 100-continue
124
1
2
3
...
HTTPヘッダはどれも128バイトになる。(参照: おまけ)
利用するファイル
以下の大きさのファイルを用意した。
100MB.dat: 104857600バイト
500MB.dat: 524288000バイト
1GB.dat: 1073741824バイト
結果
table:結果
ファイル名
100MB.dat 0.01760387421% 増加
500MB.dat 0.01631984711%増加
1GB.dat 0.01842053607%増加
平均して0.0174480858%増加している。
おまけ
生結果
計算結果の誤りが分かるように生の結果を載せる。
各ファイルの大きさ。
code:bash
$ ls -l *
-rw------- 1 Ryo staff 104857600 Jun 20 22:18 100MB.dat
-rw-r--r-- 1 Ryo staff 104876187 Jun 20 22:23 100MB_res.txt
-rw------- 1 Ryo staff 1073741824 Jun 20 22:18 1GB.dat
-rw-r--r-- 1 Ryo staff 1073939741 Jun 20 22:29 1GB_res.txt
-rw------- 1 Ryo staff 524288000 Jun 20 22:18 500MB.dat
-rw-r--r-- 1 Ryo staff 524373691 Jun 20 22:26 500MB_res.txt
レスポンスのヘッダ部分の大きさ。
以下からヘッダが0x80バイトなので128バイト。
code:bash
$ xxd 100MB_res.txt | head
00000000: 5055 5420 2f20 4854 5450 2f31 2e31 0d0a PUT / HTTP/1.1..
00000010: 486f 7374 3a20 6c6f 6361 6c68 6f73 743a Host: localhost:
00000020: 3832 3832 0d0a 5573 6572 2d41 6765 6e74 8282..User-Agent
00000030: 3a20 6375 726c 2f37 2e37 302e 300d 0a41 : curl/7.70.0..A
00000040: 6363 6570 743a 202a 2f2a 0d0a 5472 616e ccept: */*..Tran
00000050: 7366 6572 2d45 6e63 6f64 696e 673a 2063 sfer-Encoding: c
00000060: 6875 6e6b 6564 0d0a 4578 7065 6374 3a20 hunked..Expect:
00000070: 3130 302d 636f 6e74 696e 7565 0d0a 0d0a 100-continue....
00000080: 6666 6634 0d0a 0000 0000 0000 0000 0000 fff4............
00000090: 0000 0000 0000 0000 0000 0000 0000 0000 ................
ooo_res.txtからヘッダの128バイト分を引いてボディの大きさにして増加の率を出した。
チャンクのサイズがテキストは言えどあまり増えないだろうと思っていたが、実際に計測してみてあまり増えないことが分かった。
またHTTP/2だとネイティブでチャンクサポートされているはずでより最適されると思われる。
関連:「HTTP/2では「Transfer-Encoding: chunked」を使ってはいけない」
この結果は使うHTTPクライアントによってチャンクする大きさが異なると予想されるためのcurlだけではなく他のHTTPクライアントでも検証してみたかった。
ブラウザから送信しようとも考えたが、Blob/Fileだと大きさ決まってしまいそうでTransfer-Encoding: chunkedされなさそうなのと、「ブラウザのJavaScriptでPOSTリクエストのBodyをストリーミングしたいが、Chromeも未対応みたい」で触れている通り、任意のReadableStreamがHTTPのボディとして使えないことを理由にブラウザでの検証はしなかった。
あとはpvコマンドでパイプされるデータを意図的に遅くしたりしたり、すればチャンクされる頻度が高まりデータ量が増えそうな気がする。curlコマンド単体でも--limit-rateオプションで速度を指定すれば変化しそう。