Skip to content

Commit

Permalink
http2: flow control and buffer improvements
Browse files Browse the repository at this point in the history
- use bufq for send/receive of network data
- usd bufq for send/receive of stream data
- use HTTP/2 flow control with no-auto updates to control the
  amount of data we are buffering for a stream
  HTTP/2 stream window set to 128K after local tests, defined
  code constant for now
- elminiating PAUSEing nghttp2 processing when receiving data
  since a stream can now take in all DATA nghttp2 forwards

Improved scorecard and adjuste http2 stream window sizes
- scorecard improved output formatting and options default
- scorecard now also benchmarks small requests / second

Closes #10771
  • Loading branch information
icing authored and bagder committed Mar 30, 2023
1 parent 4ced75b commit 744dcf2
Show file tree
Hide file tree
Showing 10 changed files with 706 additions and 736 deletions.
35 changes: 7 additions & 28 deletions lib/bufq.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,12 +287,6 @@ bool Curl_bufq_is_full(const struct bufq *q)
return chunk_is_full(q->tail);
}

static size_t data_pass_size(struct bufq *q)
{
(void)q;
return 4*1024;
}

static struct buf_chunk *get_spare(struct bufq *q)
{
struct buf_chunk *chunk = NULL;
Expand Down Expand Up @@ -426,9 +420,12 @@ ssize_t Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len,
return nread;
}

bool Curl_bufq_peek(const struct bufq *q,
bool Curl_bufq_peek(struct bufq *q,
const unsigned char **pbuf, size_t *plen)
{
if(q->head && chunk_is_empty(q->head)) {
prune_head(q);
}
if(q->head && !chunk_is_empty(q->head)) {
chunk_peek(q->head, pbuf, plen);
return TRUE;
Expand All @@ -438,7 +435,7 @@ bool Curl_bufq_peek(const struct bufq *q,
return FALSE;
}

bool Curl_bufq_peek_at(const struct bufq *q, size_t offset,
bool Curl_bufq_peek_at(struct bufq *q, size_t offset,
const unsigned char **pbuf, size_t *plen)
{
struct buf_chunk *c = q->head;
Expand Down Expand Up @@ -502,13 +499,11 @@ ssize_t Curl_bufq_write_pass(struct bufq *q,
CURLcode *err)
{
ssize_t nwritten = 0, n;
bool prefer_direct = (len >= data_pass_size(q));

*err = CURLE_OK;
while(len) {
if(Curl_bufq_is_full(q) || (!Curl_bufq_is_empty(q) && prefer_direct)) {
/* try to make room in case we are full
* or empty the buffer when adding "large" data */
if(Curl_bufq_is_full(q)) {
/* try to make room in case we are full */
n = Curl_bufq_pass(q, writer, writer_ctx, err);
if(n < 0) {
if(*err != CURLE_AGAIN) {
Expand All @@ -519,22 +514,6 @@ ssize_t Curl_bufq_write_pass(struct bufq *q,
}
}

if(Curl_bufq_is_empty(q) && prefer_direct) {
/* empty and `data` is "large", try passing directly */
n = writer(writer_ctx, buf, len, err);
if(n < 0) {
if(*err != CURLE_AGAIN) {
/* real error, fail */
return -1;
}
/* passing would block */
n = 0;
}
buf += (size_t)n;
len -= (size_t)n;
nwritten += (size_t)n;
}

if(len) {
/* Add whatever is remaining now to bufq */
n = Curl_bufq_write(q, buf, len, err);
Expand Down
4 changes: 2 additions & 2 deletions lib/bufq.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,10 @@ ssize_t Curl_bufq_read(struct bufq *q, unsigned char *buf, size_t len,
* Repeated calls return the same information until the buffer queue
* is modified, see `Curl_bufq_skip()``
*/
bool Curl_bufq_peek(const struct bufq *q,
bool Curl_bufq_peek(struct bufq *q,
const unsigned char **pbuf, size_t *plen);

bool Curl_bufq_peek_at(const struct bufq *q, size_t offset,
bool Curl_bufq_peek_at(struct bufq *q, size_t offset,
const unsigned char **pbuf, size_t *plen);

/**
Expand Down
8 changes: 6 additions & 2 deletions lib/http.c
Original file line number Diff line number Diff line change
Expand Up @@ -4556,7 +4556,8 @@ CURLcode Curl_http_req_make(struct http_req **preq,
if(!req->path)
goto out;
}
Curl_dynhds_init(&req->headers, 128, DYN_H2_HEADERS);
Curl_dynhds_init(&req->headers, 0, DYN_H2_HEADERS);
Curl_dynhds_init(&req->trailers, 0, DYN_H2_TRAILERS);
result = CURLE_OK;

out:
Expand All @@ -4573,6 +4574,7 @@ void Curl_http_req_free(struct http_req *req)
free(req->authority);
free(req->path);
Curl_dynhds_free(&req->headers);
Curl_dynhds_free(&req->trailers);
free(req);
}
}
Expand All @@ -4594,7 +4596,8 @@ CURLcode Curl_http_resp_make(struct http_resp **presp,
if(!resp->description)
goto out;
}
Curl_dynhds_init(&resp->headers, 128, DYN_H2_HEADERS);
Curl_dynhds_init(&resp->headers, 0, DYN_H2_HEADERS);
Curl_dynhds_init(&resp->trailers, 0, DYN_H2_TRAILERS);
result = CURLE_OK;

out:
Expand All @@ -4609,6 +4612,7 @@ void Curl_http_resp_free(struct http_resp *resp)
if(resp) {
free(resp->description);
Curl_dynhds_free(&resp->headers);
Curl_dynhds_free(&resp->trailers);
if(resp->prev)
Curl_http_resp_free(resp->prev);
free(resp);
Expand Down
17 changes: 9 additions & 8 deletions lib/http.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include <pthread.h>
#endif

#include "bufq.h"
#include "dynhds.h"
#include "ws.h"

Expand Down Expand Up @@ -227,14 +228,12 @@ struct HTTP {
#ifdef USE_NGHTTP2
/*********** for HTTP/2 we store stream-local data here *************/
int32_t stream_id; /* stream we are interested in */

/* We store non-final and final response headers here, per-stream */
struct dynbuf header_recvbuf;
size_t nread_header_recvbuf; /* number of bytes in header_recvbuf fed into
upper layer */
struct dynbuf trailer_recvbuf;
const uint8_t *pausedata; /* pointer to data received in on_data_chunk */
size_t pauselen; /* the number of bytes left in data */
struct bufq h2_sendbuf; /* request body data buffere for sending */
size_t h2_send_hds_len; /* amount of bytes in first cf_send() that
are header bytes. Or 0 if not known. */
struct bufq h2_recvbuf;
size_t h2_recv_hds_len; /* how many bytes in recvbuf are headers */
struct dynhds resp_trailers;
bool close_handled; /* TRUE if stream closure is handled by libcurl */

char **push_headers; /* allocated array */
Expand Down Expand Up @@ -346,6 +345,7 @@ struct http_req {
char *authority;
char *path;
struct dynhds headers;
struct dynhds trailers;
};

/**
Expand All @@ -366,6 +366,7 @@ struct http_resp {
int status;
char *description;
struct dynhds headers;
struct dynhds trailers;
struct http_resp *prev;
};

Expand Down
Loading

0 comments on commit 744dcf2

Please sign in to comment.