Browse Source

[core] better asm for binary num to ascii string

compiler optimizers generally convert div to an equivalent mul,
though not always optimally for modulus (%).  In places where
lighttpd is using both quotient and remainder, calculate the
remainder from the quotient.

x-ref: inspiration:
  https://lemire.me/blog/2019/02/08/faster-remainders-when-the-divisor-is-a-constant-beating-compilers-and-libdivide/
  https://lemire.me/blog/2019/02/20/more-fun-with-fast-remainders-when-the-divisor-is-a-constant/
master
Glenn Strauss 2 months ago
parent
commit
05dc3d123a
  1. 8
      src/buffer.c
  2. 44
      src/h2.c
  3. 5
      src/mod_accesslog.c

8
src/buffer.c

@ -300,12 +300,10 @@ __attribute_nonnull__()
__attribute_returns_nonnull__
static char* utostr(char buf[LI_ITOSTRING_LENGTH], uintmax_t val) {
char *cur = buf+LI_ITOSTRING_LENGTH;
uintmax_t x;
do {
int mod = val % 10;
val /= 10;
/* prepend digit mod */
*(--cur) = (char) ('0' + mod);
} while (0 != val);
*(--cur) = (char) ('0' + (int)(val - (x = val/10) * 10));
} while (0 != (val = x)); /* val % 10 */
return cur;
}

44
src/h2.c

@ -1924,14 +1924,7 @@ h2_send_headers (request_st * const r, connection * const con)
const int log_response_header = r->conf.log_response_header;
const int resp_header_repeated = r->resp_header_repeated;
char status[12] = ":status: ";
int x = r->http_status; /*(expect status < 1000; should be [100-599])*/
status[11] = (x % 10) + '0';
status[10] = (x / 10 % 10) + '0';
status[9] = (x / 100) + '0';
if (log_response_header)
h2_log_response_header(r, 12, status);
char status[12] = ":status: 200";
memset(&lsx, 0, sizeof(lsxpack_header_t));
lsx.buf = status;
@ -1939,23 +1932,38 @@ h2_send_headers (request_st * const r, connection * const con)
lsx.name_len = 7;
lsx.val_offset = 9;
lsx.val_len = 3;
switch (r->http_status) {
case 200: lsx.hpack_index = LSHPACK_HDR_STATUS_200; break;
case 204: lsx.hpack_index = LSHPACK_HDR_STATUS_204; break;
case 206: lsx.hpack_index = LSHPACK_HDR_STATUS_206; break;
case 304: lsx.hpack_index = LSHPACK_HDR_STATUS_304; break;
case 400: lsx.hpack_index = LSHPACK_HDR_STATUS_400; break;
case 404: lsx.hpack_index = LSHPACK_HDR_STATUS_404; break;
case 500: lsx.hpack_index = LSHPACK_HDR_STATUS_500; break;
default:
break;
if (__builtin_expect( (200 == r->http_status), 1)) {
lsx.hpack_index = LSHPACK_HDR_STATUS_200;
}
else {
int x = r->http_status; /*(expect status < 1000; should be [100-599])*/
switch (x) {
/*case 200: lsx.hpack_index = LSHPACK_HDR_STATUS_200; break;*/
case 204: lsx.hpack_index = LSHPACK_HDR_STATUS_204; break;
case 206: lsx.hpack_index = LSHPACK_HDR_STATUS_206; break;
case 304: lsx.hpack_index = LSHPACK_HDR_STATUS_304; break;
case 400: lsx.hpack_index = LSHPACK_HDR_STATUS_400; break;
case 404: lsx.hpack_index = LSHPACK_HDR_STATUS_404; break;
case 500: lsx.hpack_index = LSHPACK_HDR_STATUS_500; break;
default:
break;
}
int nx;
status[11] += (x - (nx = x/10) * 10); /* (x % 10) */
x = nx;
status[10] += (x - (nx = x/10) * 10); /* (x / 10 % 10) */
status[9] = '0' + nx; /* (x / 100) */
}
dst = lshpack_enc_encode(encoder, dst, dst_end, &lsx);
if (dst == (unsigned char *)tb->ptr) {
h2_send_rst_stream(r, con, H2_E_INTERNAL_ERROR);
return;
}
if (log_response_header)
h2_log_response_header(r, 12, status);
/* add all headers */
data_string * const * const restrict hdata =
(data_string * const *)r->resp_headers.data;

5
src/mod_accesslog.c

@ -754,8 +754,9 @@ static int log_access_record (const request_st * const r, buffer * const b, form
} else {/*(f->opt & FORMAT_FLAG_TIME_NSEC_FRAC)*/
buffer_append_string_len(b, CONST_STR_LEN("000000000"));
}
for (ptr = b->ptr + buffer_clen(b); ns > 0; ns /= 10)
*--ptr = (ns % 10) + '0';
ptr = b->ptr + buffer_clen(b);
for (long x; ns > 0; ns = x)
*--ptr += (ns - (x = ns/10) * 10); /* ns % 10 */
}
} else {
buffer * const ts_accesslog_str = &parsed_format->ts_accesslog_str;

Loading…
Cancel
Save