Erlangのhttpc
を使用してHTTP経由でファイルをダウンロードすると、CPU使用率がcurlやwgetなどよりもはるかに高くなります。ダウンロード速度を測定するために使用しているコードは、この記事の末尾に表示されています。ファイルをダウンロードするときのCPU使用率が高い
CPU使用率が高いのは、特にローエンドのデバイスで問題になります。私はErlangを最初のRaspberry PIよりわずかに強力なARM-SoCで実行しています。このコードはCPU使用率100%、ダウンロード速度6.1 MiB/sにすぎません。カールとwgetを使用すると、CPU使用率は100%をわずかに下回り、ネットワークインターフェイス (100 MBit/sネットワークインターフェイスでは10.7 MiB/sまたは85.6 MBit/s)をほぼ完全に使用します。
ibrowseやhackneyなどの他のHTTPライブラリを使用しようとしましたが、同じ問題が引き続き発生します。私の推測では、Erlangのソケットパフォーマンスと関係がありますが、間違っている可能性があります。ですから、私の質問は、遅いダウンロード速度の正確な原因とは何か、それに対する回避策はありますか?私はhttps://github.com/puzza007/katipoのようなlibcurlを使うライブラリを知っているので、おそらく同じ問題はないでしょうが、NIFを使うライブラリを使わないほうがいいでしょう。バックbenchmarkに行く
defmodule DownloadPerformanceTest do
@testfile 'http://speed.hetzner.de/100MB.bin'
@filesize 104857600
@save_to '/dev/null'
def test() do
Application.start(:inets)
then = :erlang.system_time(:micro_seconds)
{:ok, :saved_to_file} = :httpc.request(:get, {@testfile, []}, [], [{:stream, @save_to}])
now = :erlang.system_time(:micro_seconds)
diff = now - then
bw = bandwidth_to_human_readable(@filesize, diff)
IO.puts "Download took #{:erlang.trunc(diff/1_000_000)} seconds, average speed: #{bw}"
end
defp bandwidth_to_human_readable(bytes, microseconds) do
bytes_per_second = bytes/(microseconds/1000000)
exponent = :erlang.trunc(:math.log2(bytes_per_second)/:math.log2(1024))
prefix = case exponent do
0 -> {:ok, ""}
1 -> {:ok, "Ki"}
2 -> {:ok, "Mi"}
3 -> {:ok, "Gi"}
4 -> {:ok, "Ti"}
5 -> {:ok, "Pi"}
6 -> {:ok, "Ei"}
7 -> {:ok, "Zi"}
8 -> {:ok, "Yi"}
_ -> {:error, :too_large}
end
case prefix do
{:ok, prefix} ->
quantity = Float.round(bytes_per_second/:math.pow(1024, exponent), 2)
unit = "#{prefix}B/s"
"#{quantity} #{unit}"
{:error, :too_large} ->
"#{bytes_per_second} B/s"
end
end
end
ソケット操作でこれを試しましたか?私はhttpcを使っていくつかの特質があることを知りましたが、httpダウンロードでCPU使用率が高くなる原因は何か分かりません。私の経験では、Erlangのソケットパフォーマンスは、制約のあるハードウェアであっても*非常に*良いですが、他のプロトコルライブラリを使用していない純粋なソケットプロセスを書いているため、非効率的なHTTPデータがあるかどうかはわかりませんおそらくHTTPのチャンクとヘッダーなどは比較的高価な方法で逆アセンブルされますか?) – zxq9
@ zxq9実際には:gen_tcpを使うと、カールした10.5 MiB/sに比べて、私は9.81 MiB/sで直接ダウンロードできます。私はまだホイールを再発明するのではなく、適切なHTTPライブラリを使う方が好きですが、ほとんどすべてのメンテナンスされたライブラリは、ハックニーやibrowseに基づいています。 – helios35
Erlangの世界では、最近ではHTTPについて心配し始めましたが、実際にはほんの数箇所にすぎません。Erlangの多くの仕事は一般にウェブとつながっておらず、文化にも広がっています。そのため、ErlangのWebライブラリやXML解析や、HTML解析の狂気には本当に深く関わっていません。私はおそらく、バイナリとアトムとバイナリからストリングキャストなどの間で反転する代わりに、*文字列*としてHTTPヘッダー、チャンクなどのネイティブ解析を行うことも考えています。 – zxq9