Closed hoyhoy closed 6 months ago
I cannot reproduce that with current Beast, running both with tsan and without I get clean results, e.g.
ab -k -c 8 -n 10000 https://0.0.0.0:8080/main.cpp
Benchmarking 0.0.0.0 (be patient)
Completed 1000 requests
Completed 2000 requests
Completed 3000 requests
Completed 4000 requests
Completed 5000 requests
Completed 6000 requests
Completed 7000 requests
Completed 8000 requests
Completed 9000 requests
Completed 10000 requests
Finished 10000 requests
Server Software: Boost.Beast/351
Server Hostname: 0.0.0.0
Server Port: 8080
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256
Server Temp Key: X25519 253 bits
Document Path: /main.cpp
Document Length: 5798 bytes
Concurrency Level: 8
Time taken for tests: 55.907 seconds
Complete requests: 10000
Failed requests: 0
Keep-Alive requests: 10000
Total transferred: 59200000 bytes
HTML transferred: 57980000 bytes
Requests per second: 178.87 [#/sec] (mean)
Time per request: 44.725 [ms] (mean)
Time per request: 5.591 [ms] (mean, across all concurrent requests)
Transfer rate: 1034.09 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.3 0 12
Processing: 42 45 1.5 44 52
Waiting: 0 1 0.2 1 4
Total: 43 45 1.5 44 58
Percentage of the requests served within a certain time (ms)
50% 44
66% 44
75% 44
80% 44
90% 48
95% 48
98% 48
99% 48
and not a peep from the thread sanitizer. Can you provide specifics about your steps to build (did you use b2/Jamfile or cmake? what OS, compiler, openssl versions?). Specifically, it is possible to compile with compiler defines that tell Boost, Asio or Beast to disable feature like thread safety (or thread support in general).
@hoyhoy Regarding the performance, make sure you are building the application in release mode. Boost.Beast and Boost.Asio have a lot of indirection and generic functions, which result in very slow debug executable.
If you build in release mode, you can expect around 100K req/s on a single thread and around 200K req/s with 4 threads (with small responses):
This is ApacheBench, Version 2.3 <$Revision: 1879490 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking 0.0.0.0 (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests
Server Software: Boost.Beast/353
Server Hostname: 0.0.0.0
Server Port: 8080
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256
Server Temp Key: X25519 253 bits
Document Path: /file
Document Length: 1024 bytes
Concurrency Level: 100
Time taken for tests: 0.477 seconds
Complete requests: 100000
Failed requests: 0
Keep-Alive requests: 100000
Total transferred: 114600000 bytes
HTML transferred: 102400000 bytes
Requests per second: 209536.42 [#/sec] (mean)
Time per request: 0.477 [ms] (mean)
Time per request: 0.005 [ms] (mean, across all concurrent requests)
Transfer rate: 234500.72 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 1.9 0 66
Processing: 0 0 0.4 0 28
Waiting: 0 0 0.4 0 28
Total: 0 0 2.0 0 67
Percentage of the requests served within a certain time (ms)
50% 0
66% 0
75% 0
80% 0
90% 0
95% 0
98% 1
99% 1
100% 67 (longest request)
I'm obviously running it with the clang thread-sanitizer enabled, so it's a -glldb
binary. I was testing it with more ab threads than hardware-concurrency since our SSL app is crashing in that case. It seems like bad SSL requests cause thread-safety issues in the latest boost 1.84 example implementation as well. That's what we're seeing in production.
You are correct; access to std::cerr
is not thread-safe, resulting in a ThreadSanitizer warning. If you are using C++ 20, you can encapsulate std::cerr
within a std::osyncstream
.
Please keep this issue open, as it needs to be addressed in all examples.
It's more than that though, the ssl errors aren't handled correctly in the example. There's really no canonical documentation or examples for recovering from ssl errors like truncated reads and timeouts due to the server being overloaded. We've just spent weeks debugging thread-safety and error-handling issues with our implementation, and it's still not working.
Is your i/o context multithreaded and are you using strands?
Is your i/o context multithreaded and are you using strands?
Yes, but I'm sure we're doing it wrong.
It was originally implemented based on http/server3 to replace mongoose. The example http_server_async_ssl.cpp server in boost 1.84 doesn't have the SSL disconnection crashes that we're seeing, but also it doesn't handle truncated-reads, etc.
Boost 1.84
libs/beast/example/http/server/async-ssl/http_server_async_ssl.cpp
appears to have a number of issues.(1) Seems to not be thread-safe...
(2) Running with a number of concurrent sessions causes it to fail.
My current ssl implementation is suffering from a number of the same issues. Is boost 1.84 ssl_stream not meant to be used as a high-performance https server?