More SSL_read() to fill big buffer

Once SSL_read() only get max 16K bytes (one TLS record).
In case of big buffer, should more SSL_read() to fill the buffer.

Using sample https-client to measure max income MBit/s via nload tool.
Note: set bufferevent_set_max_single_read() by 32K and add the chunk
callback to read out each piece of data.

The client sample do https request a data 900KB (the server don't use
Transfer-Encoding: chunked)
- With origin/master: max income is 2.26 MBit/s
  The chunk callback never get a piece of data > 16K.
- With this PR: max income is 2.44 MBit/s
  The chunk callback can get some piece of data 32K or more.
This commit is contained in:
Thuan Tran 2023-05-15 10:18:38 +07:00 committed by Azat Khuzhin
parent 4ab3242da1
commit ef51444f43

View File

@ -253,9 +253,10 @@ do_read(struct bufferevent_ssl *bev_ssl, int n_to_read) {
/* Requires lock */ /* Requires lock */
struct bufferevent *bev = &bev_ssl->bev.bev; struct bufferevent *bev = &bev_ssl->bev.bev;
struct evbuffer *input = bev->input; struct evbuffer *input = bev->input;
int r, n, i, n_used = 0, atmost; int r, n, i = 0, atmost;
struct evbuffer_iovec space[2]; struct evbuffer_iovec space[2];
int result = 0; int result = 0;
size_t len = 0;
if (bev_ssl->bev.read_suspended) if (bev_ssl->bev.read_suspended)
return 0; return 0;
@ -268,23 +269,30 @@ do_read(struct bufferevent_ssl *bev_ssl, int n_to_read) {
if (n < 0) if (n < 0)
return OP_ERR; return OP_ERR;
for (i=0; i<n; ++i) { for (i = 0; i < n;) {
if (bev_ssl->bev.read_suspended) if (bev_ssl->bev.read_suspended)
break; break;
bev_ssl->ssl_ops->clear_error(); bev_ssl->ssl_ops->clear_error();
r = bev_ssl->ssl_ops->read(bev_ssl->ssl, space[i].iov_base, space[i].iov_len); r = bev_ssl->ssl_ops->read(
if (r>0) { bev_ssl->ssl, (unsigned char *)space[i].iov_base + len, space[i].iov_len - len);
if (r > 0) {
result |= OP_MADE_PROGRESS; result |= OP_MADE_PROGRESS;
if (bev_ssl->read_blocked_on_write) if (bev_ssl->read_blocked_on_write)
if (clear_rbow(bev_ssl) < 0) if (clear_rbow(bev_ssl) < 0)
return OP_ERR | result; return OP_ERR | result;
++n_used;
space[i].iov_len = r;
bev_ssl->ssl_ops->decrement_buckets(bev_ssl); bev_ssl->ssl_ops->decrement_buckets(bev_ssl);
len += r;
if (space[i].iov_len - len > 0) {
continue;
} else {
space[i].iov_len = len;
len = 0;
++i;
}
} else { } else {
int err = bev_ssl->ssl_ops->get_error(bev_ssl->ssl, r); int err = bev_ssl->ssl_ops->get_error(bev_ssl->ssl, r);
bev_ssl->ssl_ops->print_err(err); bev_ssl->ssl_ops->print_err(err);
if (bev_ssl->ssl_ops->err_is_ok(err) && result & OP_MADE_PROGRESS) { if (result & OP_MADE_PROGRESS) {
/* Process existing data */ /* Process existing data */
break; break;
} else if (bev_ssl->ssl_ops->err_is_want_read(err)) { } else if (bev_ssl->ssl_ops->err_is_want_read(err)) {
@ -292,7 +300,7 @@ do_read(struct bufferevent_ssl *bev_ssl, int n_to_read) {
if (bev_ssl->read_blocked_on_write) if (bev_ssl->read_blocked_on_write)
if (clear_rbow(bev_ssl) < 0) if (clear_rbow(bev_ssl) < 0)
return OP_ERR | result; return OP_ERR | result;
} else if(bev_ssl->ssl_ops->err_is_want_write(err)) { } else if (bev_ssl->ssl_ops->err_is_want_write(err)) {
/* This read operation requires a write, and the /* This read operation requires a write, and the
* underlying is full */ * underlying is full */
if (!bev_ssl->read_blocked_on_write) if (!bev_ssl->read_blocked_on_write)
@ -306,8 +314,13 @@ do_read(struct bufferevent_ssl *bev_ssl, int n_to_read) {
} }
} }
if (n_used) { if (len > 0) {
evbuffer_commit_space(input, space, n_used); space[i].iov_len = len;
++i;
}
if (i) {
evbuffer_commit_space(input, space, i);
if (bev_ssl->underlying) if (bev_ssl->underlying)
BEV_RESET_GENERIC_READ_TIMEOUT(bev); BEV_RESET_GENERIC_READ_TIMEOUT(bev);
} }