В целях обучения я написал простой TCP-прокси на Erlang. Это работает, но у меня возникает странное падение производительности, когда я использую ab (Apache Bench) для выполнения множества параллельных запросов. Я удивляюсь не падению производительности как таковому, а масштабу падения. Бэкэнд - это nginx как веб-сервер. Мой прокси находится между ab и nginx.
Это код моего прокси.
-module(proxy).
-export([start/3]).
start(InPort, OutHost, OutPort) ->
{ok, Listen} = gen_tcp:listen(InPort, [binary, {packet, 0}, {active, once}]),
spawn(fun() -> connect(Listen, OutHost, OutPort) end).
connect(Listen, OutHost, OutPort) ->
{ok, Client} = gen_tcp:accept(Listen),
spawn(fun() -> connect(Listen, OutHost, OutPort) end),
{ok, Server} = gen_tcp:connect(OutHost, OutPort, [binary, {packet, 0}, {active, once}]),
loop(Client, Server).
loop(Client, Server) ->
receive
{tcp, Client, Data} ->
gen_tcp:send(Server, Data),
inet:setopts(Client, [{active, once}]),
loop(Client, Server);
{tcp, Server, Data} ->
gen_tcp:send(Client, Data),
inet:setopts(Server, [{active, once}]),
loop(Client, Server);
{tcp_closed, _} ->
ok
end.
Запустив 64 последовательных запроса на моем прокси, я получаю очень хороший результат.
ab -n 64 127.0.0.1:80/
Concurrency Level: 1
Time taken for tests: 0.097 seconds
Complete requests: 64
Failed requests: 0
Write errors: 0
Total transferred: 23168 bytes
HTML transferred: 9664 bytes
Requests per second: 659.79 [#/sec] (mean)
Time per request: 1.516 [ms] (mean)
Time per request: 1.516 [ms] (mean, across all concurrent requests)
Transfer rate: 233.25 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.3 0 1
Processing: 1 1 0.5 1 2
Waiting: 0 1 0.4 1 2
Total: 1 1 0.5 1 2
Percentage of the requests served within a certain time (ms)
50% 1
66% 2
75% 2
80% 2
90% 2
95% 2
98% 2
99% 2
100% 2 (longest request)
Это немного медленнее, чем использовать Apache Bench напрямую против nginx.
Но при выполнении 64 одновременных запросов на прокси производительность падает с ума
ab -n 64 -c 64 127.0.0.1:80/
Concurrency Level: 64
Time taken for tests: 2.011 seconds
Complete requests: 64
Failed requests: 0
Write errors: 0
Total transferred: 23168 bytes
HTML transferred: 9664 bytes
Requests per second: 31.82 [#/sec] (mean)
Time per request: 2011.000 [ms] (mean)
Time per request: 31.422 [ms] (mean, across all concurrent requests)
Transfer rate: 11.25 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 31 121.7 0 501
Processing: 3 1135 714.4 1001 2006
Waiting: 3 1134 714.3 1000 2005
Total: 3 1167 707.8 1001 2006
Percentage of the requests served within a certain time (ms)
50% 1001
66% 1502
75% 2003
80% 2004
90% 2005
95% 2005
98% 2005
99% 2006
100% 2006 (longest request)
В чем / где проблема? Я ожидал снижения производительности, но почему так много? Посмотрите на запросы в секунду!
Кажется, это не имеет большого значения, если я даю много потоков, используя + A. Я даже попробовал SMP, но результаты почти такие же.
Мои настройки: Windows 7 64, Intel QuadCore, 8 ГБ ОЗУ. Я получаю аналогичные результаты в Ubuntu, используя 128 одновременных запросов.
РЕДАКТИРОВАТЬ: Включено новое понимание. Общее количество запросов не имеет значения. Это просто количество одновременных запросов.