curl-library
libcurl reconnect
Date: Wed, 27 Feb 2019 10:17:42 +0300
Hello All
I have made small http server benchmark tool base on libcurl library (
https://github.com/ajax16384/ahsbt).
There are plenty number of tools with same functionality but they have
some disadvantages:
- ab (https://httpd.apache.org/docs/2.4/programs/ab.html) and wrk (
https://github.com/wg/wrk) lack http2 support
- h2load (https://nghttp2.org/documentation/h2load.1.html) has no non
keep alive mode
- go based tools (https://github.com/rakyll/hey,
https://github.com/tsenart/vegeta) has non user land friendly
thread-process usage
So tool creates threads with single multi-curl and curl_multi_wait-
curl_multi_perform loop and constantly readd easy-curl handles until all
requests are done.
Now I am stuck on strange libcurl behaviour:
then I'm trying to run test without reusing same socket connection
(CURLOPT_FORBID_REUSE==1), program starts to perform very slow and with
higher CPU usage compared to apache ab tool with same run parameters.
Test environment:
Nginx with static page (http://172.19.161.85/resp200/).
./ahsbt --tcpnagle --noreuse --connections=1 --threads=1 --requests=50000
http://172.19.161.85/resp200/
Another HTTP Server Benchmark Test 0.1
Using libcurl/7.58.0 OpenSSL/1.1.1 zlib/1.2.11 libidn2/2.0.4 libpsl/0.19.1
(+libidn2/2.0.4) nghttp2/1.30.0 librtmp/2.3
Url: http://172.19.161.85/resp200/
No Reuse
TCP Nagle
Connections count: 1
Requests count: 50000
Threads count: 1
Testing ...
Total requests count: 50000
Transfer errors count: 18825 [ 37.65% ]
Response errors count: 0 [ 0.00% ]
Min request time: 0.00 sec
Avg request time: 0.00 sec
Max request time: 0.01 sec
Measured total time: 61.67 sec
Requests per second: 810.72
ab -c 1 -n 50000 http://172.19.161.85/resp200/
Concurrency Level: 1
Time taken for tests: 6.294 seconds
Complete requests: 50000
Failed requests: 0
Total transferred: 7800000 bytes
HTML transferred: 0 bytes
Requests per second: 7944.47 [#/sec] (mean)
Time per request: 0.126 [ms] (mean)
Time per request: 0.126 [ms] (mean, across all concurrent requests)
Transfer rate: 1210.29 [Kbytes/sec] received
From strace point of view libcurl and ab doing essentially the same
(except getsockopt,getpeername,getsockname which are insignficant according
to perf):
Libcurl:
[pid 12716] socket(AF_INET, SOCK_STREAM, IPPROTO_IP) = 3
[pid 12716] fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
[pid 12716] fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
[pid 12716] connect(3, {sa_family=AF_INET, sin_port=htons(80),
sin_addr=inet_addr("172.19.161.85")}, 16) = -1 EINPROGRESS (Operation now
in progress)
[pid 12716] poll([{fd=3, events=POLLOUT|POLLWRNORM}], 1, 0) = 1 ([{fd=3,
revents=POLLOUT|POLLWRNORM}])
[pid 12716] getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
[pid 12716] getpeername(3, {sa_family=AF_INET, sin_port=htons(80),
sin_addr=inet_addr("172.19.161.85")}, [128->16]) = 0
[pid 12716] getsockname(3, {sa_family=AF_INET, sin_port=htons(43058),
sin_addr=inet_addr("172.19.161.88")}, [128->16]) = 0
[pid 12716] sendto(3, "GET /resp200/ HTTP/1.1\r\nHost: 17"..., 60,
MSG_NOSIGNAL, NULL, 0) = 60
[pid 12716] poll([{fd=3, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}], 1,
0) = 0 (Timeout)
[pid 12716] poll([{fd=3, events=POLLIN}], 1, 0) = 1 ([{fd=3,
revents=POLLIN}])
[pid 12716] poll([{fd=3, events=POLLIN|POLLPRI|POLLRDNORM|POLLRDBAND}], 1,
0) = 1 ([{fd=3, revents=POLLIN|POLLRDNORM}])
[pid 12716] recvfrom(3, "HTTP/1.1 200 OK\r\nServer: nginx/1"..., 16384, 0,
NULL, NULL) = 184
[pid 12716] close(3) = 0
Ab:
socket(AF_INET, SOCK_STREAM|SOCK_CLOEXEC, IPPROTO_IP) = 6
fcntl(6, F_GETFL) = 0x2 (flags O_RDWR)
fcntl(6, F_SETFL, O_RDWR|O_NONBLOCK) = 0
connect(6, {sa_family=AF_INET, sin_port=htons(80),
sin_addr=inet_addr("172.19.161.85")}, 16) = -1 EINPROGRESS (Operation now
in progress)
epoll_ctl(5, EPOLL_CTL_ADD, 6, {EPOLLOUT, {u32=364313568,
u64=94867601947616}}) = 0
epoll_wait(5, [{EPOLLOUT, {u32=364313568, u64=94867601947616}}], 1, 30000)
= 1
connect(6, {sa_family=AF_INET, sin_port=htons(80),
sin_addr=inet_addr("172.19.161.85")}, 16) = 0
epoll_ctl(5, EPOLL_CTL_DEL, 6, 0x7ffdeb1151bc) = 0
epoll_ctl(5, EPOLL_CTL_ADD, 6, {EPOLLIN, {u32=364313568,
u64=94867601947616}}) = 0
write(6, "", 0) = 0
write(6, "GET /resp200/ HTTP/1.0\r\nHost: 17"..., 89) = 89
epoll_wait(5, [{EPOLLIN, {u32=364313568, u64=94867601947616}}], 1, 30000) =
1
read(6, "HTTP/1.1 200 OK\r\nServer: nginx/1"..., 8192) = 156
epoll_wait(5, [{EPOLLIN, {u32=364313568, u64=94867601947616}}], 1, 30000) =
1
read(6, "", 8192) = 0
epoll_ctl(5, EPOLL_CTL_DEL, 6, 0x7ffdeb1150cc) = 0
close(6) = 0
"perf record -F 1000 --call-graph dwarf -g" points to system "connect", but
it's arguments are the same as in apache ab.
Samples: 59K of event 'cpu-clock', Event count (approx.):
59066000000
Children Self Command Shared Object
Symbol
- 99.98% 0.03% ahsbt ahsbt [.]
_Z12ThreadMethodP11SThreadDataPKcmmbbbbbl
- 99.95%
_Z12ThreadMethodP11SThreadDataPKcmmbbbbbl
- 99.48%
curl_multi_perform
- 99.42%
multi_runsingle
- 97.56%
Curl_connect
- 96.95%
Curl_setup_conn
- 96.93%
Curl_connecthost
- 96.90%
singleipconnect
- 95.98%
__libc_connect
- 95.94%
entry_SYSCALL_64_after_hwframe
- 95.94%
do_syscall_64
+ 95.91%
sys_connect
0.51% create_conn
(inlined)
+ 0.57% multi_do
(inlined)
Issue can be observed without real network (http://localhost
tests)
It would be great if You help to resolve this issue or even if You have any
idea why libcurl socket serial re-connection are so slow compared to apache
"ab" ( it may be my ignorense in libcurl api usage etc or it's a libcurl
bug) .
Thanks
Andrei
-------------------------------------------------------------------
Unsubscribe: https://cool.haxx.se/list/listinfo/curl-library
Etiquette: https://curl.haxx.se/mail/etiquette.html
Received on 2019-02-27