* feat: make client to wait when no free connections
* feat: make client to wait when no free connections
use AcquireTimer to do timeout instead of using context
* feat: make client to wait when no free connections
Add BenchmarkClientGetEndToEndWaitConn* to test heap allocation
in waiting for free connection situation
* feat: make client to wait when no free connections
Add BenchmarkHTTPClientGetEndToEndWaitConn* to test heap allocation
in waiting for free connection situation
* feat: make client to wait when no free connections
fix bug in BenchmarkHTTPClientGetEndToEndWaitConn*
* feat: make client to wait when no free connections
fix bug in TestHostClientMaxConnWaitTimeoutSuccess make it wait
longer to avoid ErrNoFreeConns on travis-ci
* feat: make client to wait when no free connections
fix do not compile benchmark(NetHTTP?)ClientGetEndToEndWaitConn
if go version < 1.11.x
* feat: make client to wait when no free connections
fix the bug that if deadline is earlier than MaxConnWaitTimeout,
still wait MaxConnWaitTimeout which later than deadline.
* feat: make client to wait when no free connections
fix race condition in TestHostClientMaxConnWaitTimeoutError
* feat: make client to wait when no free connections
fix bug in TestHostClientMaxConnWaitTimeoutWithEarlierDeadline
This means we can't skip parsing headers for GET requests anymore. This
can be seen as good as it also allows us to reject malformed GET
requests, something we didn't do before this. Performance also isn't
affect much:
benchmark old ns/op new ns/op delta
BenchmarkClientGetEndToEnd1Inmemory-16 640 641 +0.16%
BenchmarkClientGetEndToEnd10Inmemory-16 713 710 -0.42%
BenchmarkClientGetEndToEnd100Inmemory-16 732 749 +2.32%
BenchmarkClientGetEndToEnd1000Inmemory-16 759 774 +1.98%
BenchmarkClientGetEndToEnd10KInmemory-16 785 808 +2.93%
BenchmarkNetHTTPClientGetEndToEnd1Inmemory-16 5045 4954 -1.80%
BenchmarkNetHTTPClientGetEndToEnd10Inmemory-16 5806 6225 +7.22%
BenchmarkNetHTTPClientGetEndToEnd100Inmemory-16 7877 7998 +1.54%
BenchmarkNetHTTPClientGetEndToEnd1000Inmemory-16 16603 16559 -0.27%
- Some tests can't be run in parallel.
- `URI` had a pointer to `RequestHeader` which was updated with
`RequestHeader.CopyTo` which resulted in the URI pointing to the wrong
`RequestHeader` causing bugs and race conditions.
The only reason `URI` contained a pointer to `RequestHeader` was to delay the
call to `RequestHeader.Host()` until really needed. But these days instead
of parsing all headers, `RequestHeader.Host()` uses
`RequestHeader.peekRawHeader()` which is rather fast. So we can remove the
pointer in `URI` and completely decouple the two structs improving code
quality and fixing the bug.
For some reason this results in faster code on average as well:
benchmark old ns/op new ns/op delta
BenchmarkClientGetEndToEnd1Inmemory-8 1189 1369 +15.14%
BenchmarkClientGetEndToEnd10Inmemory-8 1143 1161 +1.57%
BenchmarkClientGetEndToEnd100Inmemory-8 1228 1236 +0.65%
BenchmarkClientGetEndToEnd1000Inmemory-8 1213 1213 +0.00%
BenchmarkClientGetEndToEnd10KInmemory-8 1362 1350 -0.88%
BenchmarkClientEndToEndBigResponse1Inmemory-8 139967 130070 -7.07%
BenchmarkClientEndToEndBigResponse10Inmemory-8 142233 131809 -7.33%
BenchmarkServerGet1ReqPerConn-8 1726 1593 -7.71%
BenchmarkServerGet2ReqPerConn-8 882 927 +5.10%
BenchmarkServerGet10ReqPerConn-8 440 436 -0.91%
BenchmarkServerGet10KReqPerConn-8 341 339 -0.59%
BenchmarkServerPost1ReqPerConn-8 1728 1706 -1.27%
BenchmarkServerPost2ReqPerConn-8 968 963 -0.52%
BenchmarkServerPost10ReqPerConn-8 506 505 -0.20%
BenchmarkServerPost10KReqPerConn-8 424 420 -0.94%
BenchmarkServerGet1ReqPerConn10KClients-8 1117 1051 -5.91%
BenchmarkServerGet2ReqPerConn10KClients-8 565 514 -9.03%
BenchmarkServerGet10ReqPerConn10KClients-8 390 387 -0.77%
BenchmarkServerGet100ReqPerConn10KClients-8 355 348 -1.97%
BenchmarkServerHijack-8 339 348 +2.65%
BenchmarkServerMaxConnsPerIP-8 326 325 -0.31%
BenchmarkServerTimeoutError-8 24355 24180 -0.72%
* Add `Response.SetBodyRaw` method that serves a `[]byte` slice without touching it (as an alternative to `SetBody`)
* Update various response related functions that are impacted after the incoduction of `Response.bodyRaw`
* Add a few test-cases in relation to `Response.SetBodyRaw`
Not doing this means people using Client can still inspect the response
headers when reading the body fails (for example when it is too big).
fixes#456
Previously, GET/HEAD bodies were not read. The HTTP 1.1 specification
states:
"A server SHOULD read and forward a message-body on any request; if the
request method does not include defined semantics for an entity-body,
then the message-body SHOULD be ignored when handling the request.
I suspect this code is at fault."
This change reads the body on such request and continues the previous
behavior of returning a "Content-Length" of 0 to the application.
See: https://github.com/valyala/fasthttp/issues/159
Compressing small bodies has little sense, since the compressed result size
may exceed the original body size.
This should save CPU time when the server responds with small responses.
Previously each concurrent compression could allocate huge compression state
with the size up to 1Mb each. So 10K concurrent connections could result in
10Gb of compression state in the heap.
This CL limits the number of compression states among concurrent requests
when {Append,Write}{Gzip,Deflate}* functions are called to O(GOMAXPROCS).
These functions are used by CompressHandler* for non-streaming responses,
i.e. it should cover the majority of use cases.
Memory usage for 10K concurrent connections that compress responses drops
from 10Gb to 200Mb after this CL.
These methods may help writing proper request handler wrappers
for request handlers, which may set body either via SetBodyStream*
or via usual body methods.
- Use request/response body pools.
- Defer request/response body allocation until it is really required.
- Return request/response bodies to the pool as soon as they become unused.
This minimizes the total amount of memory occupied by active request/response
bodies under high load.