Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP http_parser: don't reuse HTTPParser #24330

Closed
wants to merge 2 commits into from

Conversation

mmarchini
Copy link
Contributor

As discussed in nodejs/diagnostics#248 and
#21313, reusing HTTPParser resource
is a blocker for landing
require('async_hooks').currentAsyncResource(), since reusing an async
resource interanlly would make it infeasible to use them reliably in
WeakMaps. Two suggestions came up: have a wrapper around the HTTPParser
which we would use as the async resource, or stop reusing HTTPParser in
our HTTP server/client code.

This commit implements the latter, since we have a better GC now and
reusing HTTPParser might make sense anymore. This also will avoid one
extra JS->C++ call in some cases, which should improve performance for
these cases.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines

@nodejs-github-bot nodejs-github-bot added c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory. labels Nov 13, 2018
As discussed in nodejs/diagnostics#248 and
nodejs#21313, reusing HTTPParser resource
is a blocker for landing
`require('async_hooks').currentAsyncResource()`, since reusing an async
resource interanlly would make it infeasible to use them reliably in
WeakMaps. Two suggestions came up: have a wrapper around the HTTPParser
which we would use as the async resource, or stop reusing HTTPParser in
our HTTP server/client code.

This commit implements the latter, since we have a better GC now and
reusing HTTPParser might make sense anymore. This also will avoid one
extra JS->C++ call in some cases, which should improve performance for
these cases.
@mmarchini
Copy link
Contributor Author

mmarchini commented Nov 13, 2018

Regressions on http/client-request-body seems to be the most significant:

                                                                      confidence improvement accuracy (*)   (**)   (***)
 http/client-request-body.js method='end' len=1024 type='asc' dur=5            *     -8.12 %       ±6.52% ±8.67% ±11.29%
 http/client-request-body.js method='end' len=1024 type='buf' dur=5            *     -6.33 %       ±5.59% ±7.44%  ±9.69%
 http/client-request-body.js method='end' len=1024 type='utf' dur=5            *     -7.74 %       ±6.60% ±8.79% ±11.44%
 http/client-request-body.js method='end' len=256 type='asc' dur=5             *     -8.53 %       ±6.42% ±8.55% ±11.13%
 http/client-request-body.js method='end' len=256 type='buf' dur=5                   -4.67 %       ±5.86% ±7.80% ±10.15%
 http/client-request-body.js method='end' len=256 type='utf' dur=5             *     -6.33 %       ±5.36% ±7.13%  ±9.28%
 http/client-request-body.js method='end' len=32 type='asc' dur=5            ***    -12.60 %       ±5.93% ±7.89% ±10.27%
 http/client-request-body.js method='end' len=32 type='buf' dur=5                     0.08 %       ±6.70% ±8.91% ±11.60%
 http/client-request-body.js method='end' len=32 type='utf' dur=5              *     -7.62 %       ±6.36% ±8.47% ±11.05%
 http/client-request-body.js method='write' len=1024 type='asc' dur=5                -3.80 %       ±6.07% ±8.08% ±10.53%
 http/client-request-body.js method='write' len=1024 type='buf' dur=5        ***    -14.17 %       ±5.60% ±7.46%  ±9.70%
 http/client-request-body.js method='write' len=1024 type='utf' dur=5         **     -8.91 %       ±6.61% ±8.80% ±11.46%
 http/client-request-body.js method='write' len=256 type='asc' dur=5          **    -10.05 %       ±7.20% ±9.58% ±12.48%
 http/client-request-body.js method='write' len=256 type='buf' dur=5           *     -7.62 %       ±6.95% ±9.25% ±12.05%
 http/client-request-body.js method='write' len=256 type='utf' dur=5                 -6.19 %       ±6.24% ±8.30% ±10.81%
 http/client-request-body.js method='write' len=32 type='asc' dur=5                  -5.66 %       ±6.47% ±8.60% ±11.20%
 http/client-request-body.js method='write' len=32 type='buf' dur=5                  -1.43 %       ±5.45% ±7.27%  ±9.50%
 http/client-request-body.js method='write' len=32 type='utf' dur=5          ***    -14.11 %       ±5.77% ±7.68%  ±9.99%

Be aware that when doing many comparisons the risk of a false-positive
result increases. In this case there are 18 comparisons, you can thus
expect the following amount of false-positive results:
  0.90 false positives, when considering a   5% risk acceptance (*, **, ***),
  0.18 false positives, when considering a   1% risk acceptance (**, ***),
  0.02 false positives, when considering a 0.1% risk acceptance (***)

compare-plot

I'll see if there's anything else we can optimize to compensate for these regressions. Also, I'm not sure if we can break the HTTPParser API. It's not documented, and this PR removes the .reinitialize() method.

@mcollina @Flarna @AndreasMadsen PTAL a let me know what you think.

Full HTTP Benchmark Results
                                                                                               confidence improvement accuracy (*)    (**)   (***)
 http/bench-parser.js n=100000 len=16                                                                         -2.87 %       ±4.72%  ±6.28%  ±8.17%
 http/bench-parser.js n=100000 len=32                                                                   *     -3.76 %       ±3.61%  ±4.82%  ±6.29%
 http/bench-parser.js n=100000 len=4                                                                    *     -2.98 %       ±2.37%  ±3.15%  ±4.10%
 http/bench-parser.js n=100000 len=8                                                                          -3.20 %       ±4.06%  ±5.40%  ±7.04%
 http/check_invalid_header_char.js n=1000000 input=''                                                         -1.95 %       ±4.82%  ±6.41%  ±8.35%
 http/check_invalid_header_char.js n=1000000 input='\177'                                                     -1.12 %       ±3.00%  ±3.99%  ±5.20%
 http/check_invalid_header_char.js n=1000000 input='1'                                                         0.37 %       ±4.01%  ±5.34%  ±6.97%
 http/check_invalid_header_char.js n=1000000 input='20091'                                                    -2.47 %       ±4.19%  ±5.61%  ±7.37%
 http/check_invalid_header_char.js n=1000000 input='close'                                                    -0.95 %       ±4.13%  ±5.51%  ±7.19%
 http/check_invalid_header_char.js n=1000000 input='en-US'                                                    -1.37 %       ±4.28%  ±5.70%  ±7.43%
 http/check_invalid_header_char.js n=1000000 input='foo\\nbar'                                                -1.36 %       ±4.04%  ±5.38%  ±7.01%
 http/check_invalid_header_char.js n=1000000 input='group_acmeair'                                             2.34 %       ±3.57%  ±4.75%  ±6.20%
 http/check_invalid_header_char.js n=1000000 input='gzip'                                                     -0.10 %       ±4.40%  ±5.85%  ±7.63%
 http/check_invalid_header_char.js n=1000000 input='keep-alive'                                                1.84 %       ±4.15%  ±5.52%  ±7.18%
 http/check_invalid_header_char.js n=1000000 input='LONG_AND_INVALID'                                          0.47 %       ±1.99%  ±2.65%  ±3.44%
 http/check_invalid_header_char.js n=1000000 input='private'                                                   2.75 %       ±3.79%  ±5.07%  ±6.64%
 http/check_invalid_header_char.js n=1000000 input='SAMEORIGIN'                                               -3.61 %       ±4.07%  ±5.43%  ±7.09%
 http/check_invalid_header_char.js n=1000000 input='Sat, 07 May 2016 16:54:48 GMT'                             0.46 %       ±2.59%  ±3.45%  ±4.49%
 http/check_invalid_header_char.js n=1000000 input='text/html; charset=utf-8'                                  0.86 %       ±3.87%  ±5.15%  ±6.71%
 http/check_invalid_header_char.js n=1000000 input='text/plain'                                               -2.86 %       ±3.89%  ±5.18%  ±6.75%
 http/check_invalid_header_char.js n=1000000 input='\\t\\t\\t\\t\\t\\t\\t\\t\\t\\tFoo bar baz'                -2.64 %       ±3.54%  ±4.71%  ±6.13%
 http/check_invalid_header_char.js n=1000000 input='中文呢'                                                    2.97 %       ±4.57%  ±6.10%  ±7.98%
 http/check_is_http_token.js n=1000000 key=':'                                                                -2.30 %       ±4.08%  ±5.46%  ±7.17%
 http/check_is_http_token.js n=1000000 key='((((())))'                                                  *      5.75 %       ±5.45%  ±7.29%  ±9.57%
 http/check_is_http_token.js n=1000000 key='@@'                                                                3.72 %       ±4.72%  ±6.28%  ±8.18%
 http/check_is_http_token.js n=1000000 key='Accept-Ranges'                                                     0.29 %       ±3.70%  ±4.93%  ±6.42%
 http/check_is_http_token.js n=1000000 key=':alternate-protocol'                                              -0.01 %       ±5.30%  ±7.05%  ±9.18%
 http/check_is_http_token.js n=1000000 key='alternate-protocol:'                                              -0.11 %       ±2.14%  ±2.85%  ±3.72%
 http/check_is_http_token.js n=1000000 key='alternate-protocol'                                               -3.76 %       ±4.29%  ±5.71%  ±7.45%
 http/check_is_http_token.js n=1000000 key='alt-svc'                                                           2.00 %       ±3.56%  ±4.75%  ±6.22%
 http/check_is_http_token.js n=1000000 key='Cache-Control'                                                     2.31 %       ±3.31%  ±4.42%  ±5.77%
 http/check_is_http_token.js n=1000000 key='Connection'                                                        2.00 %       ±4.50%  ±6.00%  ±7.81%
 http/check_is_http_token.js n=1000000 key='Content-Encoding'                                                 -0.28 %       ±3.47%  ±4.61%  ±6.01%
 http/check_is_http_token.js n=1000000 key='content-length'                                                   -1.58 %       ±3.88%  ±5.18%  ±6.76%
 http/check_is_http_token.js n=1000000 key='Content-Location'                                                  0.13 %       ±2.85%  ±3.80%  ±4.96%
 http/check_is_http_token.js n=1000000 key='content-type'                                                     -2.50 %       ±3.16%  ±4.21%  ±5.49%
 http/check_is_http_token.js n=1000000 key='Content-Type'                                                      1.39 %       ±3.68%  ±4.90%  ±6.38%
 http/check_is_http_token.js n=1000000 key='date'                                                              0.34 %       ±4.66%  ±6.21%  ±8.09%
 http/check_is_http_token.js n=1000000 key='ETag'                                                             -0.92 %       ±2.93%  ±3.90%  ±5.08%
 http/check_is_http_token.js n=1000000 key='Expires'                                                           1.48 %       ±2.74%  ±3.65%  ±4.75%
 http/check_is_http_token.js n=1000000 key='Keep-Alive'                                                 *     -4.26 %       ±4.07%  ±5.44%  ±7.12%
 http/check_is_http_token.js n=1000000 key='Last-Modified'                                                    -0.46 %       ±4.21%  ±5.60%  ±7.30%
 http/check_is_http_token.js n=1000000 key='location'                                                         -3.81 %       ±4.37%  ±5.82%  ±7.60%
 http/check_is_http_token.js n=1000000 key='server'                                                           -1.71 %       ±3.16%  ±4.20%  ±5.47%
 http/check_is_http_token.js n=1000000 key='Server'                                                            1.06 %       ±4.90%  ±6.52%  ±8.49%
 http/check_is_http_token.js n=1000000 key='status'                                                           -0.61 %       ±4.00%  ±5.33%  ±6.95%
 http/check_is_http_token.js n=1000000 key='TCN'                                                               2.94 %       ±3.68%  ±4.92%  ±6.45%
 http/check_is_http_token.js n=1000000 key='Transfer-Encoding'                                                 0.45 %       ±3.12%  ±4.15%  ±5.42%
 http/check_is_http_token.js n=1000000 key='Vary'                                                             -2.76 %       ±3.58%  ±4.79%  ±6.28%
 http/check_is_http_token.js n=1000000 key='version'                                                          -4.42 %       ±4.75%  ±6.35%  ±8.32%
 http/check_is_http_token.js n=1000000 key='x-frame-options'                                                  -2.81 %       ±3.87%  ±5.15%  ±6.70%
 http/check_is_http_token.js n=1000000 key='x-xss-protection'                                                 -1.62 %       ±3.63%  ±4.83%  ±6.30%
 http/check_is_http_token.js n=1000000 key='中文呢'                                                           -0.27 %       ±5.57%  ±7.41%  ±9.64%
 http/chunked.js c=100 len=1 n=16 benchmarker='wrk'                                                           -0.15 %       ±0.49%  ±0.66%  ±0.85%
 http/chunked.js c=100 len=1 n=1 benchmarker='wrk'                                                            -0.04 %       ±0.30%  ±0.40%  ±0.52%
 http/chunked.js c=100 len=1 n=4 benchmarker='wrk'                                                            -0.10 %       ±0.31%  ±0.41%  ±0.53%
 http/chunked.js c=100 len=1 n=8 benchmarker='wrk'                                                            -0.26 %       ±0.35%  ±0.47%  ±0.61%
 http/chunked.js c=100 len=256 n=16 benchmarker='wrk'                                                          0.03 %       ±0.67%  ±0.90%  ±1.17%
 http/chunked.js c=100 len=256 n=1 benchmarker='wrk'                                                          -0.17 %       ±0.30%  ±0.41%  ±0.53%
 http/chunked.js c=100 len=256 n=4 benchmarker='wrk'                                                           0.10 %       ±0.33%  ±0.44%  ±0.57%
 http/chunked.js c=100 len=256 n=8 benchmarker='wrk'                                                          -0.02 %       ±0.28%  ±0.37%  ±0.49%
 http/chunked.js c=100 len=64 n=16 benchmarker='wrk'                                                          -0.09 %       ±0.49%  ±0.65%  ±0.85%
 http/chunked.js c=100 len=64 n=1 benchmarker='wrk'                                                            0.05 %       ±0.29%  ±0.39%  ±0.51%
 http/chunked.js c=100 len=64 n=4 benchmarker='wrk'                                                           -0.04 %       ±0.26%  ±0.34%  ±0.44%
 http/chunked.js c=100 len=64 n=8 benchmarker='wrk'                                                           -0.09 %       ±0.27%  ±0.35%  ±0.46%
 http/client-request-body.js method='end' len=1024 type='asc' dur=5                                     *     -8.12 %       ±6.52%  ±8.67% ±11.29%
 http/client-request-body.js method='end' len=1024 type='buf' dur=5                                     *     -6.33 %       ±5.59%  ±7.44%  ±9.69%
 http/client-request-body.js method='end' len=1024 type='utf' dur=5                                     *     -7.74 %       ±6.60%  ±8.79% ±11.44%
 http/client-request-body.js method='end' len=256 type='asc' dur=5                                      *     -8.53 %       ±6.42%  ±8.55% ±11.13%
 http/client-request-body.js method='end' len=256 type='buf' dur=5                                            -4.67 %       ±5.86%  ±7.80% ±10.15%
 http/client-request-body.js method='end' len=256 type='utf' dur=5                                      *     -6.33 %       ±5.36%  ±7.13%  ±9.28%
 http/client-request-body.js method='end' len=32 type='asc' dur=5                                     ***    -12.60 %       ±5.93%  ±7.89% ±10.27%
 http/client-request-body.js method='end' len=32 type='buf' dur=5                                              0.08 %       ±6.70%  ±8.91% ±11.60%
 http/client-request-body.js method='end' len=32 type='utf' dur=5                                       *     -7.62 %       ±6.36%  ±8.47% ±11.05%
 http/client-request-body.js method='write' len=1024 type='asc' dur=5                                         -3.80 %       ±6.07%  ±8.08% ±10.53%
 http/client-request-body.js method='write' len=1024 type='buf' dur=5                                 ***    -14.17 %       ±5.60%  ±7.46%  ±9.70%
 http/client-request-body.js method='write' len=1024 type='utf' dur=5                                  **     -8.91 %       ±6.61%  ±8.80% ±11.46%
 http/client-request-body.js method='write' len=256 type='asc' dur=5                                   **    -10.05 %       ±7.20%  ±9.58% ±12.48%
 http/client-request-body.js method='write' len=256 type='buf' dur=5                                    *     -7.62 %       ±6.95%  ±9.25% ±12.05%
 http/client-request-body.js method='write' len=256 type='utf' dur=5                                          -6.19 %       ±6.24%  ±8.30% ±10.81%
 http/client-request-body.js method='write' len=32 type='asc' dur=5                                           -5.66 %       ±6.47%  ±8.60% ±11.20%
 http/client-request-body.js method='write' len=32 type='buf' dur=5                                           -1.43 %       ±5.45%  ±7.27%  ±9.50%
 http/client-request-body.js method='write' len=32 type='utf' dur=5                                   ***    -14.11 %       ±5.77%  ±7.68%  ±9.99%
 http/cluster.js c=500 len=102400 type='buffer' benchmarker='wrk'                                              1.55 %       ±3.87%  ±5.16%  ±6.71%
 http/cluster.js c=500 len=102400 type='bytes' benchmarker='wrk'                                              -0.05 %       ±4.17%  ±5.55%  ±7.22%
 http/cluster.js c=500 len=1024 type='buffer' benchmarker='wrk'                                               -1.69 %       ±3.57%  ±4.75%  ±6.19%
 http/cluster.js c=500 len=1024 type='bytes' benchmarker='wrk'                                                -2.44 %       ±3.45%  ±4.59%  ±5.97%
 http/cluster.js c=500 len=4 type='buffer' benchmarker='wrk'                                                   0.37 %       ±3.51%  ±4.67%  ±6.08%
 http/cluster.js c=500 len=4 type='bytes' benchmarker='wrk'                                                    0.46 %       ±4.00%  ±5.32%  ±6.92%
 http/cluster.js c=50 len=102400 type='buffer' benchmarker='wrk'                                        *     -3.43 %       ±3.40%  ±4.53%  ±5.90%
 http/cluster.js c=50 len=102400 type='bytes' benchmarker='wrk'                                               -2.09 %       ±3.42%  ±4.56%  ±5.94%
 http/cluster.js c=50 len=1024 type='buffer' benchmarker='wrk'                                                 0.26 %       ±2.49%  ±3.32%  ±4.32%
 http/cluster.js c=50 len=1024 type='bytes' benchmarker='wrk'                                                  1.52 %       ±2.58%  ±3.43%  ±4.46%
 http/cluster.js c=50 len=4 type='buffer' benchmarker='wrk'                                                   -1.20 %       ±2.62%  ±3.48%  ±4.54%
 http/cluster.js c=50 len=4 type='bytes' benchmarker='wrk'                                                    -0.57 %       ±2.60%  ±3.46%  ±4.51%
 http/create-clientrequest.js n=1000000 len=1                                                                 -2.40 %       ±3.74%  ±4.97%  ±6.48%
 http/create-clientrequest.js n=1000000 len=128                                                               -2.20 %       ±4.04%  ±5.38%  ±7.00%
 http/create-clientrequest.js n=1000000 len=16                                                                -1.70 %       ±3.81%  ±5.07%  ±6.60%
 http/create-clientrequest.js n=1000000 len=32                                                         **     -5.55 %       ±3.99%  ±5.32%  ±6.96%
 http/create-clientrequest.js n=1000000 len=64                                                                -2.73 %       ±3.83%  ±5.10%  ±6.63%
 http/create-clientrequest.js n=1000000 len=8                                                                 -1.84 %       ±3.59%  ±4.78%  ±6.23%
 http/end-vs-write-end.js method='end' c=100 len=1048576 type='asc' benchmarker='wrk'                          2.03 %       ±5.86%  ±7.80% ±10.16%
 http/end-vs-write-end.js method='end' c=100 len=1048576 type='buf' benchmarker='wrk'                         -0.29 %       ±6.21%  ±8.26% ±10.75%
 http/end-vs-write-end.js method='end' c=100 len=1048576 type='utf' benchmarker='wrk'                         -1.81 %       ±5.65%  ±7.52%  ±9.79%
 http/end-vs-write-end.js method='end' c=100 len=131072 type='asc' benchmarker='wrk'                           0.01 %       ±3.75%  ±4.99%  ±6.50%
 http/end-vs-write-end.js method='end' c=100 len=131072 type='buf' benchmarker='wrk'                           0.50 %       ±4.05%  ±5.39%  ±7.02%
 http/end-vs-write-end.js method='end' c=100 len=131072 type='utf' benchmarker='wrk'                           0.35 %       ±3.92%  ±5.22%  ±6.80%
 http/end-vs-write-end.js method='end' c=100 len=262144 type='asc' benchmarker='wrk'                           3.11 %       ±3.91%  ±5.23%  ±6.84%
 http/end-vs-write-end.js method='end' c=100 len=262144 type='buf' benchmarker='wrk'                           1.14 %       ±4.90%  ±6.52%  ±8.49%
 http/end-vs-write-end.js method='end' c=100 len=262144 type='utf' benchmarker='wrk'                          -1.23 %       ±4.11%  ±5.48%  ±7.13%
 http/end-vs-write-end.js method='end' c=100 len=65536 type='asc' benchmarker='wrk'                     *      2.51 %       ±2.48%  ±3.30%  ±4.30%
 http/end-vs-write-end.js method='end' c=100 len=65536 type='buf' benchmarker='wrk'                            4.03 %       ±5.86%  ±7.80% ±10.16%
 http/end-vs-write-end.js method='end' c=100 len=65536 type='utf' benchmarker='wrk'                           -0.43 %       ±2.38%  ±3.17%  ±4.12%
 http/end-vs-write-end.js method='write' c=100 len=1048576 type='asc' benchmarker='wrk'                       -3.62 %       ±4.49%  ±5.97%  ±7.77%
 http/end-vs-write-end.js method='write' c=100 len=1048576 type='buf' benchmarker='wrk'                        0.63 %       ±7.58% ±10.09% ±13.14%
 http/end-vs-write-end.js method='write' c=100 len=1048576 type='utf' benchmarker='wrk'                       -2.76 %       ±4.68%  ±6.23%  ±8.11%
 http/end-vs-write-end.js method='write' c=100 len=131072 type='asc' benchmarker='wrk'                        -1.66 %       ±2.00%  ±2.66%  ±3.46%
 http/end-vs-write-end.js method='write' c=100 len=131072 type='buf' benchmarker='wrk'                        -1.95 %       ±3.71%  ±4.94%  ±6.44%
 http/end-vs-write-end.js method='write' c=100 len=131072 type='utf' benchmarker='wrk'                  *     -3.29 %       ±3.15%  ±4.20%  ±5.48%
 http/end-vs-write-end.js method='write' c=100 len=262144 type='asc' benchmarker='wrk'                        -0.31 %       ±3.29%  ±4.38%  ±5.70%
 http/end-vs-write-end.js method='write' c=100 len=262144 type='buf' benchmarker='wrk'                        -2.42 %       ±4.17%  ±5.55%  ±7.22%
 http/end-vs-write-end.js method='write' c=100 len=262144 type='utf' benchmarker='wrk'                        -1.59 %       ±2.62%  ±3.49%  ±4.55%
 http/end-vs-write-end.js method='write' c=100 len=65536 type='asc' benchmarker='wrk'                         -1.98 %       ±2.92%  ±3.88%  ±5.05%
 http/end-vs-write-end.js method='write' c=100 len=65536 type='buf' benchmarker='wrk'                         -1.14 %       ±5.20%  ±6.92%  ±9.01%
 http/end-vs-write-end.js method='write' c=100 len=65536 type='utf' benchmarker='wrk'                         -1.34 %       ±3.09%  ±4.11%  ±5.36%
 http/headers.js n=1000 duplicates=100 benchmarker='wrk'                                                      -0.21 %       ±2.05%  ±2.72%  ±3.55%
 http/headers.js n=1000 duplicates=1 benchmarker='wrk'                                                        -0.13 %       ±2.38%  ±3.17%  ±4.13%
 http/headers.js n=10 duplicates=100 benchmarker='wrk'                                                        -0.66 %       ±4.58%  ±6.10%  ±7.94%
 http/headers.js n=10 duplicates=1 benchmarker='wrk'                                                          -0.48 %       ±3.99%  ±5.31%  ±6.94%
 http/http_server_for_chunky_client.js type='send' n=2000 len=1                                               -1.08 %       ±9.30% ±12.38% ±16.11%
 http/http_server_for_chunky_client.js type='send' n=2000 len=128                                             -2.23 %       ±9.81% ±13.05% ±16.98%
 http/http_server_for_chunky_client.js type='send' n=2000 len=16                                               3.12 %      ±10.26% ±13.65% ±17.78%
 http/http_server_for_chunky_client.js type='send' n=2000 len=32                                               1.30 %      ±11.09% ±14.75% ±19.20%
 http/http_server_for_chunky_client.js type='send' n=2000 len=4                                                4.60 %      ±11.80% ±15.71% ±20.46%
 http/http_server_for_chunky_client.js type='send' n=2000 len=64                                               7.43 %       ±9.88% ±13.16% ±17.14%
 http/http_server_for_chunky_client.js type='send' n=2000 len=8                                               -3.12 %      ±10.83% ±14.41% ±18.77%
 http/http_server_for_chunky_client.js type='send' n=500 len=1                                                 0.77 %       ±4.93%  ±6.57%  ±8.55%
 http/http_server_for_chunky_client.js type='send' n=500 len=128                                        *     -6.70 %       ±5.66%  ±7.56%  ±9.88%
 http/http_server_for_chunky_client.js type='send' n=500 len=16                                                1.04 %       ±6.39%  ±8.50% ±11.07%
 http/http_server_for_chunky_client.js type='send' n=500 len=32                                               -0.63 %       ±6.21%  ±8.27% ±10.78%
 http/http_server_for_chunky_client.js type='send' n=500 len=4                                                -0.61 %       ±6.00%  ±7.99% ±10.41%
 http/http_server_for_chunky_client.js type='send' n=500 len=64                                               -3.43 %       ±5.05%  ±6.72%  ±8.76%
 http/http_server_for_chunky_client.js type='send' n=500 len=8                                                 2.63 %       ±6.24%  ±8.30% ±10.80%
 http/http_server_for_chunky_client.js type='send' n=50 len=1                                                 -0.35 %       ±5.31%  ±7.07%  ±9.21%
 http/http_server_for_chunky_client.js type='send' n=50 len=128                                                0.96 %       ±5.03%  ±6.72%  ±8.78%
 http/http_server_for_chunky_client.js type='send' n=50 len=16                                                 1.77 %       ±6.02%  ±8.01% ±10.43%
 http/http_server_for_chunky_client.js type='send' n=50 len=32                                                -2.29 %       ±5.69%  ±7.58%  ±9.87%
 http/http_server_for_chunky_client.js type='send' n=50 len=4                                                 -0.49 %       ±5.50%  ±7.32%  ±9.53%
 http/http_server_for_chunky_client.js type='send' n=50 len=64                                                 4.48 %       ±5.31%  ±7.08%  ±9.22%
 http/http_server_for_chunky_client.js type='send' n=50 len=8                                                 -1.81 %       ±5.92%  ±7.88% ±10.27%
 http/http_server_for_chunky_client.js type='send' n=5 len=1                                                  -2.76 %       ±5.12%  ±6.82%  ±8.88%
 http/http_server_for_chunky_client.js type='send' n=5 len=128                                                -1.40 %       ±8.42% ±11.22% ±14.64%
 http/http_server_for_chunky_client.js type='send' n=5 len=16                                                 -3.46 %       ±9.00% ±11.98% ±15.62%
 http/http_server_for_chunky_client.js type='send' n=5 len=32                                                  6.27 %       ±8.85% ±11.79% ±15.36%
 http/http_server_for_chunky_client.js type='send' n=5 len=4                                                  -2.48 %       ±7.84% ±10.43% ±13.58%
 http/http_server_for_chunky_client.js type='send' n=5 len=64                                                  0.57 %       ±7.18%  ±9.55% ±12.44%
 http/http_server_for_chunky_client.js type='send' n=5 len=8                                                   1.25 %       ±8.12% ±10.82% ±14.09%
 http/set_header.js n=1000000 value='Connection'                                                              -0.18 %       ±2.35%  ±3.13%  ±4.08%
 http/set_header.js n=1000000 value='Content-Length'                                                   **     -3.13 %       ±1.97%  ±2.62%  ±3.42%
 http/set_header.js n=1000000 value='Content-Type'                                                     **      4.40 %       ±3.12%  ±4.16%  ±5.43%
 http/set_header.js n=1000000 value='Set-Cookie'                                                              -0.47 %       ±2.23%  ±2.97%  ±3.87%
 http/set_header.js n=1000000 value='Transfer-Encoding'                                                       -0.99 %       ±2.50%  ±3.34%  ±4.38%
 http/set_header.js n=1000000 value='Vary'                                                                     0.63 %       ±3.02%  ±4.02%  ±5.25%
 http/set_header.js n=1000000 value='X-Powered-By'                                                             1.11 %       ±2.15%  ±2.87%  ±3.74%
 http/set-header.js res='normal' benchmarker='wrk'                                                     **     -5.08 %       ±3.81%  ±5.07%  ±6.59%
 http/set-header.js res='setHeader' benchmarker='wrk'                                                         -1.82 %       ±4.05%  ±5.39%  ±7.01%
 http/set-header.js res='setHeaderWH' benchmarker='wrk'                                                       -2.22 %       ±4.15%  ±5.53%  ±7.21%
 http/simple.js chunkedEnc=0 c=500 chunks=1 len=102400 type='buffer' benchmarker='wrk'                        -0.57 %       ±5.01%  ±6.67%  ±8.68%
 http/simple.js chunkedEnc=0 c=500 chunks=1 len=102400 type='bytes' benchmarker='wrk'                         -0.63 %       ±2.70%  ±3.60%  ±4.68%
 http/simple.js chunkedEnc=0 c=500 chunks=1 len=1024 type='buffer' benchmarker='wrk'                          -2.54 %       ±4.77%  ±6.35%  ±8.27%
 http/simple.js chunkedEnc=0 c=500 chunks=1 len=1024 type='bytes' benchmarker='wrk'                            0.11 %       ±4.59%  ±6.10%  ±7.95%
 http/simple.js chunkedEnc=0 c=500 chunks=1 len=4 type='buffer' benchmarker='wrk'                              3.52 %       ±4.76%  ±6.33%  ±8.24%
 http/simple.js chunkedEnc=0 c=500 chunks=1 len=4 type='bytes' benchmarker='wrk'                               0.23 %       ±3.93%  ±5.23%  ±6.81%
 http/simple.js chunkedEnc=0 c=500 chunks=4 len=102400 type='buffer' benchmarker='wrk'                        -0.64 %       ±5.56%  ±7.40%  ±9.64%
 http/simple.js chunkedEnc=0 c=500 chunks=4 len=102400 type='bytes' benchmarker='wrk'                         -2.00 %       ±5.13%  ±6.82%  ±8.89%
 http/simple.js chunkedEnc=0 c=500 chunks=4 len=1024 type='buffer' benchmarker='wrk'                          -0.84 %       ±3.74%  ±4.97%  ±6.47%
 http/simple.js chunkedEnc=0 c=500 chunks=4 len=1024 type='bytes' benchmarker='wrk'                           -1.44 %       ±4.31%  ±5.74%  ±7.48%
 http/simple.js chunkedEnc=0 c=500 chunks=4 len=4 type='buffer' benchmarker='wrk'                              0.64 %       ±5.27%  ±7.01%  ±9.12%
 http/simple.js chunkedEnc=0 c=500 chunks=4 len=4 type='bytes' benchmarker='wrk'                               0.77 %       ±4.63%  ±6.16%  ±8.01%
 http/simple.js chunkedEnc=0 c=50 chunks=1 len=102400 type='buffer' benchmarker='wrk'                         -1.89 %       ±4.29%  ±5.71%  ±7.44%
 http/simple.js chunkedEnc=0 c=50 chunks=1 len=102400 type='bytes' benchmarker='wrk'                           0.91 %       ±2.29%  ±3.05%  ±4.00%
 http/simple.js chunkedEnc=0 c=50 chunks=1 len=1024 type='buffer' benchmarker='wrk'                           -1.53 %       ±4.33%  ±5.76%  ±7.49%
 http/simple.js chunkedEnc=0 c=50 chunks=1 len=1024 type='bytes' benchmarker='wrk'                            -2.75 %       ±3.84%  ±5.11%  ±6.66%
 http/simple.js chunkedEnc=0 c=50 chunks=1 len=4 type='buffer' benchmarker='wrk'                               0.24 %       ±4.02%  ±5.35%  ±6.97%
 http/simple.js chunkedEnc=0 c=50 chunks=1 len=4 type='bytes' benchmarker='wrk'                               -0.84 %       ±3.46%  ±4.60%  ±5.99%
 http/simple.js chunkedEnc=0 c=50 chunks=4 len=102400 type='buffer' benchmarker='wrk'                          2.48 %       ±5.43%  ±7.23%  ±9.41%
 http/simple.js chunkedEnc=0 c=50 chunks=4 len=102400 type='bytes' benchmarker='wrk'                           0.13 %       ±3.03%  ±4.03%  ±5.25%
 http/simple.js chunkedEnc=0 c=50 chunks=4 len=1024 type='buffer' benchmarker='wrk'                           -1.72 %       ±3.07%  ±4.09%  ±5.32%
 http/simple.js chunkedEnc=0 c=50 chunks=4 len=1024 type='bytes' benchmarker='wrk'                            -0.47 %       ±3.95%  ±5.26%  ±6.85%
 http/simple.js chunkedEnc=0 c=50 chunks=4 len=4 type='buffer' benchmarker='wrk'                               1.16 %       ±4.20%  ±5.59%  ±7.28%
 http/simple.js chunkedEnc=0 c=50 chunks=4 len=4 type='bytes' benchmarker='wrk'                               -1.61 %       ±3.09%  ±4.11%  ±5.35%
 http/simple.js chunkedEnc=1 c=500 chunks=1 len=102400 type='buffer' benchmarker='wrk'                        -4.29 %       ±4.77%  ±6.35%  ±8.27%
 http/simple.js chunkedEnc=1 c=500 chunks=1 len=102400 type='bytes' benchmarker='wrk'                         -0.74 %       ±3.88%  ±5.17%  ±6.73%
 http/simple.js chunkedEnc=1 c=500 chunks=1 len=1024 type='buffer' benchmarker='wrk'                          -0.06 %       ±5.12%  ±6.81%  ±8.87%
 http/simple.js chunkedEnc=1 c=500 chunks=1 len=1024 type='bytes' benchmarker='wrk'                            2.09 %       ±4.51%  ±6.00%  ±7.81%
 http/simple.js chunkedEnc=1 c=500 chunks=1 len=4 type='buffer' benchmarker='wrk'                             -1.42 %       ±4.60%  ±6.12%  ±7.98%
 http/simple.js chunkedEnc=1 c=500 chunks=1 len=4 type='bytes' benchmarker='wrk'                               3.07 %       ±3.90%  ±5.18%  ±6.75%
 http/simple.js chunkedEnc=1 c=500 chunks=4 len=102400 type='buffer' benchmarker='wrk'                         0.36 %       ±4.04%  ±5.38%  ±7.00%
 http/simple.js chunkedEnc=1 c=500 chunks=4 len=102400 type='bytes' benchmarker='wrk'                         -1.99 %       ±3.71%  ±4.94%  ±6.43%
 http/simple.js chunkedEnc=1 c=500 chunks=4 len=1024 type='buffer' benchmarker='wrk'                          -1.53 %       ±4.45%  ±5.92%  ±7.70%
 http/simple.js chunkedEnc=1 c=500 chunks=4 len=1024 type='bytes' benchmarker='wrk'                           -1.68 %       ±4.93%  ±6.56%  ±8.54%
 http/simple.js chunkedEnc=1 c=500 chunks=4 len=4 type='buffer' benchmarker='wrk'                             -0.22 %       ±5.78%  ±7.69% ±10.01%
 http/simple.js chunkedEnc=1 c=500 chunks=4 len=4 type='bytes' benchmarker='wrk'                               1.39 %       ±4.41%  ±5.87%  ±7.64%
 http/simple.js chunkedEnc=1 c=50 chunks=1 len=102400 type='buffer' benchmarker='wrk'                          0.53 %       ±4.79%  ±6.37%  ±8.30%
 http/simple.js chunkedEnc=1 c=50 chunks=1 len=102400 type='bytes' benchmarker='wrk'                          -0.86 %       ±2.03%  ±2.70%  ±3.51%
 http/simple.js chunkedEnc=1 c=50 chunks=1 len=1024 type='buffer' benchmarker='wrk'                            2.60 %       ±3.74%  ±4.98%  ±6.49%
 http/simple.js chunkedEnc=1 c=50 chunks=1 len=1024 type='bytes' benchmarker='wrk'                            -0.39 %       ±3.99%  ±5.32%  ±6.93%
 http/simple.js chunkedEnc=1 c=50 chunks=1 len=4 type='buffer' benchmarker='wrk'                              -1.30 %       ±3.77%  ±5.02%  ±6.54%
 http/simple.js chunkedEnc=1 c=50 chunks=1 len=4 type='bytes' benchmarker='wrk'                                1.49 %       ±3.60%  ±4.79%  ±6.23%
 http/simple.js chunkedEnc=1 c=50 chunks=4 len=102400 type='buffer' benchmarker='wrk'                          1.13 %       ±4.63%  ±6.17%  ±8.04%
 http/simple.js chunkedEnc=1 c=50 chunks=4 len=102400 type='bytes' benchmarker='wrk'                          -0.38 %       ±2.61%  ±3.47%  ±4.53%
 http/simple.js chunkedEnc=1 c=50 chunks=4 len=1024 type='buffer' benchmarker='wrk'                            1.27 %       ±3.24%  ±4.31%  ±5.62%
 http/simple.js chunkedEnc=1 c=50 chunks=4 len=1024 type='bytes' benchmarker='wrk'                            -0.92 %       ±2.75%  ±3.66%  ±4.76%
 http/simple.js chunkedEnc=1 c=50 chunks=4 len=4 type='buffer' benchmarker='wrk'                              -3.05 %       ±3.11%  ±4.13%  ±5.38%
 http/simple.js chunkedEnc=1 c=50 chunks=4 len=4 type='bytes' benchmarker='wrk'                                1.37 %       ±3.83%  ±5.10%  ±6.64%
 http/upgrade.js n=1000                                                                                **     -5.39 %       ±3.59%  ±4.78%  ±6.23%
 http/upgrade.js n=5                                                                                          -0.94 %       ±2.73%  ±3.63%  ±4.72%

Be aware that when doing many comparisons the risk of a false-positive
result increases. In this case there are 217 comparisons, you can thus
expect the following amount of false-positive results:
  10.85 false positives, when considering a   5% risk acceptance (*, **, ***),
  2.17 false positives, when considering a   1% risk acceptance (**, ***),
  0.22 false positives, when considering a 0.1% risk acceptance (***)
Notifying upstream projects of job completion
Finished: SUCCESS

(edit by @AndreasMadsen: fixed formatting in <details>.)

@mmarchini
Copy link
Contributor Author

@AndreasMadsen
Copy link
Member

AndreasMadsen commented Nov 14, 2018

Yeah, http/client-request-body.js doesn't look good. There are some others that could be problematic too.


Increased Benchmark CI to 100 runs. There are quite a few comparisons, so I would like a good low confidence threshold (alpha) if possible.

https://ci.nodejs.org/view/Node.js%20benchmark/job/benchmark-node-micro-benchmarks/274/

It will take quite a while, so feel free to stop it if there is something else that is more important.

@addaleax
Copy link
Member

Picking only the most significant results:


                                                                                               confidence improvement accuracy (*)   (**)   (***)
 http/client-request-body.js method='end' len=1024 type='asc' dur=5                                   ***     -7.39 %       ±3.44% ±4.54%  ±5.83%
 http/client-request-body.js method='end' len=1024 type='utf' dur=5                                   ***     -5.50 %       ±3.18% ±4.19%  ±5.38%
 http/client-request-body.js method='end' len=256 type='asc' dur=5                                    ***     -5.59 %       ±3.11% ±4.10%  ±5.27%
 http/client-request-body.js method='end' len=32 type='buf' dur=5                                     ***     -6.26 %       ±3.18% ±4.19%  ±5.38%
 http/client-request-body.js method='write' len=1024 type='asc' dur=5                                 ***     -6.94 %       ±3.52% ±4.65%  ±5.97%
 http/client-request-body.js method='write' len=1024 type='utf' dur=5                                 ***     -6.67 %       ±3.54% ±4.67%  ±5.99%
 http/client-request-body.js method='write' len=256 type='asc' dur=5                                  ***     -5.65 %       ±3.17% ±4.18%  ±5.37%
 http/client-request-body.js method='write' len=256 type='buf' dur=5                                  ***     -7.99 %       ±2.79% ±3.67%  ±4.72%
 http/client-request-body.js method='write' len=256 type='utf' dur=5                                  ***     -6.70 %       ±3.34% ±4.41%  ±5.66%
 http/client-request-body.js method='write' len=32 type='asc' dur=5                                   ***     -6.13 %       ±3.56% ±4.69%  ±6.03%
 http/client-request-body.js method='write' len=32 type='buf' dur=5                                   ***     -6.48 %       ±3.47% ±4.57%  ±5.87%
 http/client-request-body.js method='write' len=32 type='utf' dur=5                                   ***     -6.78 %       ±3.31% ±4.36%  ±5.60%
 http/set_header.js n=1000000 value='Connection'                                                      ***      2.81 %       ±1.31% ±1.72%  ±2.21%
 http/set_header.js n=1000000 value='Content-Length'                                                  ***      2.77 %       ±0.87% ±1.15%  ±1.48%
 http/set_header.js n=1000000 value='Content-Type'                                                    ***      2.70 %       ±1.30% ±1.71%  ±2.20%
 http/set_header.js n=1000000 value='Set-Cookie'                                                      ***      2.90 %       ±1.14% ±1.51%  ±1.94%
 http/set_header.js n=1000000 value='Transfer-Encoding'                                               ***      2.34 %       ±1.23% ±1.62%  ±2.08%
 http/set_header.js n=1000000 value='X-Powered-By'                                                    ***      3.64 %       ±1.30% ±1.71%  ±2.20%
 http/upgrade.js n=5                                                                                  ***     -4.00 %       ±1.54% ±2.03%  ±2.61%

Tbh, I am not a fan of doing this – I was actually thinking about introducing similar mechanisms for other parts of Node, because there is noticable overhead associated with creating C++ objects. If we want less of a performance impact, we probably need to address that in V8 in some way before going this route…

@Flarna
Copy link
Member

Flarna commented Nov 16, 2018

@mmarchini As you pinged me to comment on this. I'm sorry but I feel not qualified to rate the results of these benchmarks. Clearly more overhead is bad but I can't tell the impact of these micro benchmarks to real world apps. I'm sure there are others in node community with more experience in this then me.

@addaleax Just for my personal interest. Do you have some hint or link to a more in depth info what exactly is causing the overhead with C++ objects? e.g. is it the need that GC has to call a finalizer or the crossing of JS/C++ border? I googled around but haven't found details.

@addaleax
Copy link
Member

@Flarna It’s the crossing of the JS/C++ border – there’s a lot of overhead in both directions… I didn’t see GC pop up as a significant slowdown in benchmarks, actually. And I wouldn’t expect finalizers to come with a lot of overhead, as that doesn’t require V8 to change engine state in some way…

@mmarchini
Copy link
Contributor Author

Tbh, I am not a fan of doing this

The goal here is to make currentAsyncResource() return a unique resource for each async operation. Another approach @Flarna suggested is wrapping HTTPParser and using this wrapper as the resource. But this solution would have the same performance implications I think.

I'm open to suggestions :)
In the meantime, I'll try to optimize this approach.

I was actually thinking about introducing similar mechanisms for other parts of Node, because there is noticable overhead associated with creating C++ objects.

I think it's a good performance optimization as long as it doesn't hurt Node.js debugability and observability.

If we want less of a performance impact, we probably need to address that in V8 in some way before going this route…

That would help I think. @hashseed @bmeurer any thoughts on this?

@addaleax
Copy link
Member

Another approach @Flarna suggested is wrapping HTTPParser and using this wrapper as the resource.

I mean, the IncomingMessage object is essentially that wrapper, right…? That would work for me…

@Flarna
Copy link
Member

Flarna commented Nov 16, 2018

Sounds good; using IncomingMessage has one more advantage - it's already public so one less undocumented/internal object exposed. I'm not yet that familiar with the node source code but it seems to me that HTTPParser is "automatically" an AsyncResource as it is a subclass of AsyncWrap. Not sure if this is moved easily from C++ to Javascript.

@mmarchini
Copy link
Contributor Author

I like this idea, I'm trying it right now :)

@mmarchini
Copy link
Contributor Author

IncomingMessage works for HTTPParser.REQUEST :D

Should we use ClientRequest for HTTPParser.RESPONSE? (ref: https://github.com/nodejs/node/blob/master/lib/_http_client.js#L631-L635)

@mcollina
Copy link
Member

mcollina commented Nov 20, 2018 via email

@Flarna
Copy link
Member

Flarna commented Nov 20, 2018

Using ClientRequest sound reasonable in current implementation even it's not that intuitive that a parser used for the response is bound to the object used for the request.
Once again async hooks expose implementation details here - but I think it's out of scope of this PR to tackle this.

I think we should not use the same resource type (e.g. HTTPPARSER) for both cases if the object passed is different.

@Flarna
Copy link
Member

Flarna commented Nov 21, 2018

It’s the crossing of the JS/C++ border – there’s a lot of overhead in both directions…

@addaleax Hmm, but why is it slower then. The initial approach doesn't increase the number of native calls just changes from reinitialize to createParser which is mostly doing the same.

@AndreasMadsen
Copy link
Member

It’s the crossing of the JS/C++ border – there’s a lot of overhead in both directions…

Regarding that and previusely work that have been done using JavaScript. Would it not be possible to compile llhttp or http_parser to WebAssembly and remove that overhead?

@Drieger Drieger mentioned this pull request Dec 17, 2018
4 tasks
@mmarchini
Copy link
Contributor Author

Closing in favor of #25094

@mmarchini mmarchini closed this Dec 17, 2018
addaleax pushed a commit to Drieger/node that referenced this pull request Apr 21, 2019
Change resource being used, previously HTTParser was being reused.
We are now using IncomingMessage and ClientRequest objects.  The goal
here is to make the async resource unique for each async operatio

Refs: nodejs#24330
Refs: nodejs/diagnostics#248
Refs: nodejs#21313

Co-authored-by: Matheus Marchini <mat@mmarchini.me>
mmarchini pushed a commit that referenced this pull request Apr 22, 2019
Change resource being used, previously HTTParser was being reused.
We are now using IncomingMessage and ClientRequest objects.  The goal
here is to make the async resource unique for each async operatio

Refs: #24330
Refs: nodejs/diagnostics#248
Refs: #21313

Co-authored-by: Matheus Marchini <mat@mmarchini.me>

PR-URL: #25094
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: Benedikt Meurer <benedikt.meurer@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. lib / src Issues and PRs related to general changes in the lib or src directory.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants