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

http: various performance improvements #10558

Merged
merged 9 commits into from Jan 11, 2017

Conversation

@mscdex
Contributor

mscdex commented Dec 31, 2016

These commits bring 3-11% performance increase (this is on top of the performance improvements made recently in #10445, #10443, and #6533). The performance increases are greater when you start setting/adding more headers than the http benchmarks currently use (just 2 currently).

When using the 'simple' http benchmark, I had to reduce the http client benchmarker duration by half (5 seconds) and reduce the number of runs to 10 (from the default of 30) to get the results back in a reasonable amount of time, especially with the newly added benchmark parameter. This allowed me to finish benchmarking in a little over 4.5 hours, whereas before with the original duration and 30 runs it was still running after 18 hours (when it technically should have finished -- even taking into account overhead since a single run doesn't last exactly the duration specified).

With that being said, here are the results with those modified benchmarking settings:

                                                                                               improvement significant      p.value
 http/simple.js res="normal" c=50 chunks=0 length=1024 type="buffer" benchmarker="wrk"              7.32 %         *** 3.688222e-09
 http/simple.js res="normal" c=50 chunks=0 length=1024 type="bytes" benchmarker="wrk"               6.33 %         *** 2.198646e-07
 http/simple.js res="normal" c=50 chunks=0 length=102400 type="buffer" benchmarker="wrk"            5.98 %         *** 8.444083e-09
 http/simple.js res="normal" c=50 chunks=0 length=102400 type="bytes" benchmarker="wrk"             1.71 %             5.654903e-02
 http/simple.js res="normal" c=50 chunks=0 length=4 type="buffer" benchmarker="wrk"                 6.75 %         *** 4.882309e-06
 http/simple.js res="normal" c=50 chunks=0 length=4 type="bytes" benchmarker="wrk"                  8.36 %         *** 5.103912e-10
 http/simple.js res="normal" c=50 chunks=1 length=1024 type="buffer" benchmarker="wrk"              7.00 %         *** 5.923557e-08
 http/simple.js res="normal" c=50 chunks=1 length=1024 type="bytes" benchmarker="wrk"               5.91 %         *** 9.026994e-07
 http/simple.js res="normal" c=50 chunks=1 length=102400 type="buffer" benchmarker="wrk"            6.87 %         *** 5.115533e-10
 http/simple.js res="normal" c=50 chunks=1 length=102400 type="bytes" benchmarker="wrk"            -0.56 %             4.997734e-01
 http/simple.js res="normal" c=50 chunks=1 length=4 type="buffer" benchmarker="wrk"                 7.06 %         *** 9.929058e-07
 http/simple.js res="normal" c=50 chunks=1 length=4 type="bytes" benchmarker="wrk"                  7.99 %         *** 1.538373e-09
 http/simple.js res="normal" c=50 chunks=4 length=1024 type="buffer" benchmarker="wrk"              9.10 %         *** 1.348325e-07
 http/simple.js res="normal" c=50 chunks=4 length=1024 type="bytes" benchmarker="wrk"               0.23 %             5.229137e-01
 http/simple.js res="normal" c=50 chunks=4 length=102400 type="buffer" benchmarker="wrk"            7.51 %         *** 1.106307e-11
 http/simple.js res="normal" c=50 chunks=4 length=102400 type="bytes" benchmarker="wrk"             1.12 %             2.529282e-01
 http/simple.js res="normal" c=50 chunks=4 length=4 type="buffer" benchmarker="wrk"                 9.56 %         *** 9.803919e-09
 http/simple.js res="normal" c=50 chunks=4 length=4 type="bytes" benchmarker="wrk"                  0.06 %             8.710531e-01
 http/simple.js res="normal" c=500 chunks=0 length=1024 type="buffer" benchmarker="wrk"             7.50 %         *** 1.055653e-05
 http/simple.js res="normal" c=500 chunks=0 length=1024 type="bytes" benchmarker="wrk"              7.24 %         *** 6.617968e-08
 http/simple.js res="normal" c=500 chunks=0 length=102400 type="buffer" benchmarker="wrk"           5.83 %         *** 2.168064e-06
 http/simple.js res="normal" c=500 chunks=0 length=102400 type="bytes" benchmarker="wrk"            0.45 %             5.161448e-01
 http/simple.js res="normal" c=500 chunks=0 length=4 type="buffer" benchmarker="wrk"                8.66 %         *** 3.537589e-07
 http/simple.js res="normal" c=500 chunks=0 length=4 type="bytes" benchmarker="wrk"                 7.71 %         *** 1.655858e-06
 http/simple.js res="normal" c=500 chunks=1 length=1024 type="buffer" benchmarker="wrk"             5.22 %         *** 1.379880e-05
 http/simple.js res="normal" c=500 chunks=1 length=1024 type="bytes" benchmarker="wrk"              4.26 %         *** 1.961713e-06
 http/simple.js res="normal" c=500 chunks=1 length=102400 type="buffer" benchmarker="wrk"           7.52 %         *** 1.537612e-06
 http/simple.js res="normal" c=500 chunks=1 length=102400 type="bytes" benchmarker="wrk"            0.25 %             6.697942e-01
 http/simple.js res="normal" c=500 chunks=1 length=4 type="buffer" benchmarker="wrk"                7.42 %         *** 3.138037e-06
 http/simple.js res="normal" c=500 chunks=1 length=4 type="bytes" benchmarker="wrk"                 7.42 %         *** 2.934613e-06
 http/simple.js res="normal" c=500 chunks=4 length=1024 type="buffer" benchmarker="wrk"             7.27 %         *** 1.925539e-06
 http/simple.js res="normal" c=500 chunks=4 length=1024 type="bytes" benchmarker="wrk"              3.05 %         *** 3.470258e-06
 http/simple.js res="normal" c=500 chunks=4 length=102400 type="buffer" benchmarker="wrk"           8.53 %         *** 8.922735e-09
 http/simple.js res="normal" c=500 chunks=4 length=102400 type="bytes" benchmarker="wrk"            2.10 %           * 3.249854e-02
 http/simple.js res="normal" c=500 chunks=4 length=4 type="buffer" benchmarker="wrk"                9.68 %         *** 8.849623e-11
 http/simple.js res="normal" c=500 chunks=4 length=4 type="bytes" benchmarker="wrk"                 4.11 %         *** 2.105516e-04
 http/simple.js res="setHeader" c=50 chunks=0 length=1024 type="buffer" benchmarker="wrk"           8.17 %         *** 1.632875e-08
 http/simple.js res="setHeader" c=50 chunks=0 length=1024 type="bytes" benchmarker="wrk"            8.10 %         *** 3.557907e-08
 http/simple.js res="setHeader" c=50 chunks=0 length=102400 type="buffer" benchmarker="wrk"         5.60 %         *** 3.508730e-05
 http/simple.js res="setHeader" c=50 chunks=0 length=102400 type="bytes" benchmarker="wrk"          1.34 %           * 1.388335e-02
 http/simple.js res="setHeader" c=50 chunks=0 length=4 type="buffer" benchmarker="wrk"              8.41 %         *** 1.808168e-09
 http/simple.js res="setHeader" c=50 chunks=0 length=4 type="bytes" benchmarker="wrk"               7.22 %         *** 1.431984e-07
 http/simple.js res="setHeader" c=50 chunks=1 length=1024 type="buffer" benchmarker="wrk"           8.31 %         *** 8.101591e-08
 http/simple.js res="setHeader" c=50 chunks=1 length=1024 type="bytes" benchmarker="wrk"            6.02 %         *** 4.761886e-05
 http/simple.js res="setHeader" c=50 chunks=1 length=102400 type="buffer" benchmarker="wrk"         6.51 %         *** 3.062989e-07
 http/simple.js res="setHeader" c=50 chunks=1 length=102400 type="bytes" benchmarker="wrk"          0.24 %             7.525069e-01
 http/simple.js res="setHeader" c=50 chunks=1 length=4 type="buffer" benchmarker="wrk"              7.10 %         *** 1.525359e-06
 http/simple.js res="setHeader" c=50 chunks=1 length=4 type="bytes" benchmarker="wrk"               6.57 %         *** 8.604833e-09
 http/simple.js res="setHeader" c=50 chunks=4 length=1024 type="buffer" benchmarker="wrk"           9.10 %         *** 2.257903e-09
 http/simple.js res="setHeader" c=50 chunks=4 length=1024 type="bytes" benchmarker="wrk"           -0.59 %           * 3.725369e-02
 http/simple.js res="setHeader" c=50 chunks=4 length=102400 type="buffer" benchmarker="wrk"         8.10 %         *** 7.263169e-10
 http/simple.js res="setHeader" c=50 chunks=4 length=102400 type="bytes" benchmarker="wrk"          1.06 %             1.969950e-01
 http/simple.js res="setHeader" c=50 chunks=4 length=4 type="buffer" benchmarker="wrk"             11.29 %         *** 3.677319e-09
 http/simple.js res="setHeader" c=50 chunks=4 length=4 type="bytes" benchmarker="wrk"               0.72 %             5.166339e-02
 http/simple.js res="setHeader" c=500 chunks=0 length=1024 type="buffer" benchmarker="wrk"          8.78 %         *** 9.781154e-10
 http/simple.js res="setHeader" c=500 chunks=0 length=1024 type="bytes" benchmarker="wrk"           9.76 %         *** 1.518366e-10
 http/simple.js res="setHeader" c=500 chunks=0 length=102400 type="buffer" benchmarker="wrk"        6.38 %         *** 7.752881e-07
 http/simple.js res="setHeader" c=500 chunks=0 length=102400 type="bytes" benchmarker="wrk"         0.77 %             1.230367e-01
 http/simple.js res="setHeader" c=500 chunks=0 length=4 type="buffer" benchmarker="wrk"             5.72 %         *** 7.548957e-05
 http/simple.js res="setHeader" c=500 chunks=0 length=4 type="bytes" benchmarker="wrk"              7.88 %         *** 1.533032e-11
 http/simple.js res="setHeader" c=500 chunks=1 length=1024 type="buffer" benchmarker="wrk"          7.58 %         *** 7.720209e-08
 http/simple.js res="setHeader" c=500 chunks=1 length=1024 type="bytes" benchmarker="wrk"           6.57 %         *** 1.119938e-07
 http/simple.js res="setHeader" c=500 chunks=1 length=102400 type="buffer" benchmarker="wrk"        6.72 %         *** 6.689565e-07
 http/simple.js res="setHeader" c=500 chunks=1 length=102400 type="bytes" benchmarker="wrk"         1.32 %           * 2.304825e-02
 http/simple.js res="setHeader" c=500 chunks=1 length=4 type="buffer" benchmarker="wrk"             6.18 %         *** 2.418794e-06
 http/simple.js res="setHeader" c=500 chunks=1 length=4 type="bytes" benchmarker="wrk"              6.51 %         *** 4.905086e-05
 http/simple.js res="setHeader" c=500 chunks=4 length=1024 type="buffer" benchmarker="wrk"          7.99 %         *** 2.740359e-09
 http/simple.js res="setHeader" c=500 chunks=4 length=1024 type="bytes" benchmarker="wrk"           5.16 %         *** 2.070415e-06
 http/simple.js res="setHeader" c=500 chunks=4 length=102400 type="buffer" benchmarker="wrk"        8.49 %         *** 3.867745e-07
 http/simple.js res="setHeader" c=500 chunks=4 length=102400 type="bytes" benchmarker="wrk"         1.87 %          ** 4.240368e-03
 http/simple.js res="setHeader" c=500 chunks=4 length=4 type="buffer" benchmarker="wrk"             9.21 %         *** 3.996481e-09
 http/simple.js res="setHeader" c=500 chunks=4 length=4 type="bytes" benchmarker="wrk"              5.97 %         *** 6.721432e-09
 http/simple.js res="setHeaderWH" c=50 chunks=0 length=1024 type="buffer" benchmarker="wrk"         7.90 %         *** 1.810239e-07
 http/simple.js res="setHeaderWH" c=50 chunks=0 length=1024 type="bytes" benchmarker="wrk"          6.88 %         *** 3.428408e-06
 http/simple.js res="setHeaderWH" c=50 chunks=0 length=102400 type="buffer" benchmarker="wrk"       5.32 %         *** 2.453555e-07
 http/simple.js res="setHeaderWH" c=50 chunks=0 length=102400 type="bytes" benchmarker="wrk"        2.16 %           * 2.768038e-02
 http/simple.js res="setHeaderWH" c=50 chunks=0 length=4 type="buffer" benchmarker="wrk"            7.95 %         *** 4.600429e-08
 http/simple.js res="setHeaderWH" c=50 chunks=0 length=4 type="bytes" benchmarker="wrk"             9.72 %         *** 3.555558e-09
 http/simple.js res="setHeaderWH" c=50 chunks=1 length=1024 type="buffer" benchmarker="wrk"         6.85 %         *** 6.685907e-09
 http/simple.js res="setHeaderWH" c=50 chunks=1 length=1024 type="bytes" benchmarker="wrk"          6.59 %         *** 5.100999e-12
 http/simple.js res="setHeaderWH" c=50 chunks=1 length=102400 type="buffer" benchmarker="wrk"       5.98 %         *** 1.976488e-08
 http/simple.js res="setHeaderWH" c=50 chunks=1 length=102400 type="bytes" benchmarker="wrk"        0.34 %             7.409726e-01
 http/simple.js res="setHeaderWH" c=50 chunks=1 length=4 type="buffer" benchmarker="wrk"            7.10 %         *** 1.609698e-08
 http/simple.js res="setHeaderWH" c=50 chunks=1 length=4 type="bytes" benchmarker="wrk"             6.17 %         *** 4.184348e-06
 http/simple.js res="setHeaderWH" c=50 chunks=4 length=1024 type="buffer" benchmarker="wrk"         7.86 %         *** 1.076794e-08
 http/simple.js res="setHeaderWH" c=50 chunks=4 length=1024 type="bytes" benchmarker="wrk"         -0.17 %             6.353906e-01
 http/simple.js res="setHeaderWH" c=50 chunks=4 length=102400 type="buffer" benchmarker="wrk"       7.40 %         *** 1.169940e-08
 http/simple.js res="setHeaderWH" c=50 chunks=4 length=102400 type="bytes" benchmarker="wrk"        0.88 %             4.654874e-01
 http/simple.js res="setHeaderWH" c=50 chunks=4 length=4 type="buffer" benchmarker="wrk"            8.24 %         *** 1.181670e-08
 http/simple.js res="setHeaderWH" c=50 chunks=4 length=4 type="bytes" benchmarker="wrk"             0.06 %             8.565252e-01
 http/simple.js res="setHeaderWH" c=500 chunks=0 length=1024 type="buffer" benchmarker="wrk"        6.76 %         *** 2.827915e-08
 http/simple.js res="setHeaderWH" c=500 chunks=0 length=1024 type="bytes" benchmarker="wrk"         7.09 %         *** 2.026343e-07
 http/simple.js res="setHeaderWH" c=500 chunks=0 length=102400 type="buffer" benchmarker="wrk"      6.91 %         *** 1.757360e-08
 http/simple.js res="setHeaderWH" c=500 chunks=0 length=102400 type="bytes" benchmarker="wrk"       1.17 %             7.434941e-02
 http/simple.js res="setHeaderWH" c=500 chunks=0 length=4 type="buffer" benchmarker="wrk"           6.97 %         *** 4.805588e-06
 http/simple.js res="setHeaderWH" c=500 chunks=0 length=4 type="bytes" benchmarker="wrk"            7.47 %         *** 6.128214e-06
 http/simple.js res="setHeaderWH" c=500 chunks=1 length=1024 type="buffer" benchmarker="wrk"        6.13 %         *** 4.073914e-06
 http/simple.js res="setHeaderWH" c=500 chunks=1 length=1024 type="bytes" benchmarker="wrk"         5.01 %         *** 1.285283e-07
 http/simple.js res="setHeaderWH" c=500 chunks=1 length=102400 type="buffer" benchmarker="wrk"      6.72 %         *** 7.269783e-07
 http/simple.js res="setHeaderWH" c=500 chunks=1 length=102400 type="bytes" benchmarker="wrk"       1.74 %          ** 3.253656e-03
 http/simple.js res="setHeaderWH" c=500 chunks=1 length=4 type="buffer" benchmarker="wrk"           5.71 %         *** 3.753727e-05
 http/simple.js res="setHeaderWH" c=500 chunks=1 length=4 type="bytes" benchmarker="wrk"            5.92 %         *** 2.036796e-07
 http/simple.js res="setHeaderWH" c=500 chunks=4 length=1024 type="buffer" benchmarker="wrk"        8.42 %         *** 1.564555e-09
 http/simple.js res="setHeaderWH" c=500 chunks=4 length=1024 type="bytes" benchmarker="wrk"         4.12 %         *** 1.636968e-05
 http/simple.js res="setHeaderWH" c=500 chunks=4 length=102400 type="buffer" benchmarker="wrk"      8.30 %         *** 1.528112e-08
 http/simple.js res="setHeaderWH" c=500 chunks=4 length=102400 type="bytes" benchmarker="wrk"      -0.41 %             3.825369e-01
 http/simple.js res="setHeaderWH" c=500 chunks=4 length=4 type="buffer" benchmarker="wrk"           9.25 %         *** 3.030151e-11
 http/simple.js res="setHeaderWH" c=500 chunks=4 length=4 type="bytes" benchmarker="wrk"            5.56 %         *** 1.334783e-06


When adding 3 custom headers in the 'setHeaderWH' case for example, you can see a greater increase:

                                                                                               improvement significant      p.value
 http/simple.js res="normal" c=50 chunks=0 length=1024 type="buffer" benchmarker="wrk"              7.77 %         *** 1.601361e-05
 http/simple.js res="normal" c=50 chunks=0 length=1024 type="bytes" benchmarker="wrk"               9.08 %         *** 1.121818e-09
 http/simple.js res="normal" c=50 chunks=0 length=102400 type="buffer" benchmarker="wrk"            6.65 %         *** 1.661088e-05
 http/simple.js res="normal" c=50 chunks=0 length=102400 type="bytes" benchmarker="wrk"             0.63 %             3.675953e-01
 http/simple.js res="normal" c=50 chunks=0 length=4 type="buffer" benchmarker="wrk"                 6.36 %         *** 1.071347e-05
 http/simple.js res="normal" c=50 chunks=0 length=4 type="bytes" benchmarker="wrk"                  7.53 %         *** 1.164565e-07
 http/simple.js res="normal" c=50 chunks=1 length=1024 type="buffer" benchmarker="wrk"              7.89 %         *** 2.980547e-07
 http/simple.js res="normal" c=50 chunks=1 length=1024 type="bytes" benchmarker="wrk"               7.66 %         *** 8.650294e-08
 http/simple.js res="normal" c=50 chunks=1 length=102400 type="buffer" benchmarker="wrk"            6.14 %         *** 1.055995e-06
 http/simple.js res="normal" c=50 chunks=1 length=102400 type="bytes" benchmarker="wrk"             0.99 %             1.902222e-01
 http/simple.js res="normal" c=50 chunks=1 length=4 type="buffer" benchmarker="wrk"                 8.55 %         *** 9.155390e-10
 http/simple.js res="normal" c=50 chunks=1 length=4 type="bytes" benchmarker="wrk"                  6.76 %         *** 1.052775e-09
 http/simple.js res="normal" c=50 chunks=4 length=1024 type="buffer" benchmarker="wrk"              9.13 %         *** 2.542129e-08
 http/simple.js res="normal" c=50 chunks=4 length=1024 type="bytes" benchmarker="wrk"              -0.28 %             4.029347e-01
 http/simple.js res="normal" c=50 chunks=4 length=102400 type="buffer" benchmarker="wrk"            8.56 %         *** 1.195479e-09
 http/simple.js res="normal" c=50 chunks=4 length=102400 type="bytes" benchmarker="wrk"             3.24 %             1.101345e-01
 http/simple.js res="normal" c=50 chunks=4 length=4 type="buffer" benchmarker="wrk"                 8.85 %         *** 1.233388e-10
 http/simple.js res="normal" c=50 chunks=4 length=4 type="bytes" benchmarker="wrk"                 -0.06 %             8.685515e-01
 http/simple.js res="normal" c=500 chunks=0 length=1024 type="buffer" benchmarker="wrk"             8.42 %         *** 2.652444e-07
 http/simple.js res="normal" c=500 chunks=0 length=1024 type="bytes" benchmarker="wrk"              7.62 %         *** 1.331863e-06
 http/simple.js res="normal" c=500 chunks=0 length=102400 type="buffer" benchmarker="wrk"           6.48 %         *** 2.695242e-06
 http/simple.js res="normal" c=500 chunks=0 length=102400 type="bytes" benchmarker="wrk"            1.69 %          ** 6.529191e-03
 http/simple.js res="normal" c=500 chunks=0 length=4 type="buffer" benchmarker="wrk"                8.44 %         *** 8.656604e-10
 http/simple.js res="normal" c=500 chunks=0 length=4 type="bytes" benchmarker="wrk"                 8.50 %         *** 1.355492e-06
 http/simple.js res="normal" c=500 chunks=1 length=1024 type="buffer" benchmarker="wrk"             7.02 %         *** 9.199390e-06
 http/simple.js res="normal" c=500 chunks=1 length=1024 type="bytes" benchmarker="wrk"              5.14 %         *** 5.819643e-08
 http/simple.js res="normal" c=500 chunks=1 length=102400 type="buffer" benchmarker="wrk"           6.35 %         *** 1.255342e-06
 http/simple.js res="normal" c=500 chunks=1 length=102400 type="bytes" benchmarker="wrk"            0.18 %             6.315421e-01
 http/simple.js res="normal" c=500 chunks=1 length=4 type="buffer" benchmarker="wrk"                7.16 %         *** 9.359637e-07
 http/simple.js res="normal" c=500 chunks=1 length=4 type="bytes" benchmarker="wrk"                 9.56 %         *** 1.078578e-08
 http/simple.js res="normal" c=500 chunks=4 length=1024 type="buffer" benchmarker="wrk"             8.05 %         *** 5.406988e-08
 http/simple.js res="normal" c=500 chunks=4 length=1024 type="bytes" benchmarker="wrk"              6.16 %         *** 1.830028e-09
 http/simple.js res="normal" c=500 chunks=4 length=102400 type="buffer" benchmarker="wrk"           7.99 %         *** 3.395783e-07
 http/simple.js res="normal" c=500 chunks=4 length=102400 type="bytes" benchmarker="wrk"            1.44 %             1.194225e-01
 http/simple.js res="normal" c=500 chunks=4 length=4 type="buffer" benchmarker="wrk"                8.78 %         *** 1.523263e-09
 http/simple.js res="normal" c=500 chunks=4 length=4 type="bytes" benchmarker="wrk"                 5.10 %         *** 7.574540e-07
 http/simple.js res="setHeader" c=50 chunks=0 length=1024 type="buffer" benchmarker="wrk"           9.29 %         *** 1.280683e-08
 http/simple.js res="setHeader" c=50 chunks=0 length=1024 type="bytes" benchmarker="wrk"            9.95 %         *** 1.584752e-07
 http/simple.js res="setHeader" c=50 chunks=0 length=102400 type="buffer" benchmarker="wrk"         6.83 %         *** 1.742157e-08
 http/simple.js res="setHeader" c=50 chunks=0 length=102400 type="bytes" benchmarker="wrk"          1.38 %          ** 5.483820e-03
 http/simple.js res="setHeader" c=50 chunks=0 length=4 type="buffer" benchmarker="wrk"              8.05 %         *** 8.117180e-08
 http/simple.js res="setHeader" c=50 chunks=0 length=4 type="bytes" benchmarker="wrk"               8.39 %         *** 5.710765e-10
 http/simple.js res="setHeader" c=50 chunks=1 length=1024 type="buffer" benchmarker="wrk"           8.66 %         *** 1.183858e-08
 http/simple.js res="setHeader" c=50 chunks=1 length=1024 type="bytes" benchmarker="wrk"            5.46 %         *** 1.684719e-08
 http/simple.js res="setHeader" c=50 chunks=1 length=102400 type="buffer" benchmarker="wrk"         6.98 %         *** 1.822605e-09
 http/simple.js res="setHeader" c=50 chunks=1 length=102400 type="bytes" benchmarker="wrk"         -0.11 %             8.195283e-01
 http/simple.js res="setHeader" c=50 chunks=1 length=4 type="buffer" benchmarker="wrk"              8.25 %         *** 1.101647e-06
 http/simple.js res="setHeader" c=50 chunks=1 length=4 type="bytes" benchmarker="wrk"               7.55 %         *** 3.233031e-06
 http/simple.js res="setHeader" c=50 chunks=4 length=1024 type="buffer" benchmarker="wrk"           9.50 %         *** 6.194324e-09
 http/simple.js res="setHeader" c=50 chunks=4 length=1024 type="bytes" benchmarker="wrk"            0.44 %             2.160161e-01
 http/simple.js res="setHeader" c=50 chunks=4 length=102400 type="buffer" benchmarker="wrk"         9.00 %         *** 2.026993e-10
 http/simple.js res="setHeader" c=50 chunks=4 length=102400 type="bytes" benchmarker="wrk"          3.13 %          ** 1.171021e-03
 http/simple.js res="setHeader" c=50 chunks=4 length=4 type="buffer" benchmarker="wrk"              8.65 %         *** 2.244983e-07
 http/simple.js res="setHeader" c=50 chunks=4 length=4 type="bytes" benchmarker="wrk"               0.51 %             9.793385e-02
 http/simple.js res="setHeader" c=500 chunks=0 length=1024 type="buffer" benchmarker="wrk"          6.55 %         *** 1.372787e-05
 http/simple.js res="setHeader" c=500 chunks=0 length=1024 type="bytes" benchmarker="wrk"           9.26 %         *** 3.045767e-10
 http/simple.js res="setHeader" c=500 chunks=0 length=102400 type="buffer" benchmarker="wrk"        6.96 %         *** 9.700479e-06
 http/simple.js res="setHeader" c=500 chunks=0 length=102400 type="bytes" benchmarker="wrk"         0.93 %             5.513154e-02
 http/simple.js res="setHeader" c=500 chunks=0 length=4 type="buffer" benchmarker="wrk"             7.92 %         *** 9.842509e-07
 http/simple.js res="setHeader" c=500 chunks=0 length=4 type="bytes" benchmarker="wrk"              8.26 %         *** 2.497220e-07
 http/simple.js res="setHeader" c=500 chunks=1 length=1024 type="buffer" benchmarker="wrk"          6.43 %         *** 3.543546e-05
 http/simple.js res="setHeader" c=500 chunks=1 length=1024 type="bytes" benchmarker="wrk"           5.06 %         *** 3.949956e-06
 http/simple.js res="setHeader" c=500 chunks=1 length=102400 type="buffer" benchmarker="wrk"        8.19 %         *** 1.144397e-07
 http/simple.js res="setHeader" c=500 chunks=1 length=102400 type="bytes" benchmarker="wrk"         1.08 %          ** 4.206755e-03
 http/simple.js res="setHeader" c=500 chunks=1 length=4 type="buffer" benchmarker="wrk"             6.50 %         *** 1.028961e-07
 http/simple.js res="setHeader" c=500 chunks=1 length=4 type="bytes" benchmarker="wrk"              8.16 %         *** 1.984112e-10
 http/simple.js res="setHeader" c=500 chunks=4 length=1024 type="buffer" benchmarker="wrk"          8.34 %         *** 1.201055e-09
 http/simple.js res="setHeader" c=500 chunks=4 length=1024 type="bytes" benchmarker="wrk"           4.56 %         *** 3.211769e-06
 http/simple.js res="setHeader" c=500 chunks=4 length=102400 type="buffer" benchmarker="wrk"       10.43 %         *** 5.400673e-09
 http/simple.js res="setHeader" c=500 chunks=4 length=102400 type="bytes" benchmarker="wrk"         2.24 %           * 3.267481e-02
 http/simple.js res="setHeader" c=500 chunks=4 length=4 type="buffer" benchmarker="wrk"             9.89 %         *** 7.214477e-09
 http/simple.js res="setHeader" c=500 chunks=4 length=4 type="bytes" benchmarker="wrk"              5.40 %         *** 1.465118e-05
 http/simple.js res="setHeaderWH" c=50 chunks=0 length=1024 type="buffer" benchmarker="wrk"        10.52 %         *** 8.904727e-10
 http/simple.js res="setHeaderWH" c=50 chunks=0 length=1024 type="bytes" benchmarker="wrk"         10.94 %         *** 2.688616e-10
 http/simple.js res="setHeaderWH" c=50 chunks=0 length=102400 type="buffer" benchmarker="wrk"       9.00 %         *** 6.729648e-09
 http/simple.js res="setHeaderWH" c=50 chunks=0 length=102400 type="bytes" benchmarker="wrk"        1.81 %          ** 7.444911e-03
 http/simple.js res="setHeaderWH" c=50 chunks=0 length=4 type="buffer" benchmarker="wrk"           11.95 %         *** 7.684982e-11
 http/simple.js res="setHeaderWH" c=50 chunks=0 length=4 type="bytes" benchmarker="wrk"            13.92 %         *** 8.301877e-11
 http/simple.js res="setHeaderWH" c=50 chunks=1 length=1024 type="buffer" benchmarker="wrk"        10.40 %         *** 3.490284e-09
 http/simple.js res="setHeaderWH" c=50 chunks=1 length=1024 type="bytes" benchmarker="wrk"         10.40 %         *** 5.392976e-11
 http/simple.js res="setHeaderWH" c=50 chunks=1 length=102400 type="buffer" benchmarker="wrk"       9.55 %         *** 1.432894e-09
 http/simple.js res="setHeaderWH" c=50 chunks=1 length=102400 type="bytes" benchmarker="wrk"        2.11 %           * 1.452478e-02
 http/simple.js res="setHeaderWH" c=50 chunks=1 length=4 type="buffer" benchmarker="wrk"           11.19 %         *** 3.085235e-13
 http/simple.js res="setHeaderWH" c=50 chunks=1 length=4 type="bytes" benchmarker="wrk"            10.91 %         *** 2.346356e-11
 http/simple.js res="setHeaderWH" c=50 chunks=4 length=1024 type="buffer" benchmarker="wrk"        12.13 %         *** 5.259254e-13
 http/simple.js res="setHeaderWH" c=50 chunks=4 length=1024 type="bytes" benchmarker="wrk"          0.15 %             7.129618e-01
 http/simple.js res="setHeaderWH" c=50 chunks=4 length=102400 type="buffer" benchmarker="wrk"      10.40 %         *** 1.480122e-10
 http/simple.js res="setHeaderWH" c=50 chunks=4 length=102400 type="bytes" benchmarker="wrk"        1.51 %             1.786063e-01
 http/simple.js res="setHeaderWH" c=50 chunks=4 length=4 type="buffer" benchmarker="wrk"           11.76 %         *** 2.442914e-10
 http/simple.js res="setHeaderWH" c=50 chunks=4 length=4 type="bytes" benchmarker="wrk"             0.40 %             2.534618e-01
 http/simple.js res="setHeaderWH" c=500 chunks=0 length=1024 type="buffer" benchmarker="wrk"       10.31 %         *** 3.108517e-06
 http/simple.js res="setHeaderWH" c=500 chunks=0 length=1024 type="bytes" benchmarker="wrk"        11.50 %         *** 3.775474e-09
 http/simple.js res="setHeaderWH" c=500 chunks=0 length=102400 type="buffer" benchmarker="wrk"      7.27 %         *** 2.105709e-05
 http/simple.js res="setHeaderWH" c=500 chunks=0 length=102400 type="bytes" benchmarker="wrk"       1.86 %           * 2.036897e-02
 http/simple.js res="setHeaderWH" c=500 chunks=0 length=4 type="buffer" benchmarker="wrk"           9.54 %         *** 7.382276e-09
 http/simple.js res="setHeaderWH" c=500 chunks=0 length=4 type="bytes" benchmarker="wrk"           10.39 %         *** 3.321337e-09
 http/simple.js res="setHeaderWH" c=500 chunks=1 length=1024 type="buffer" benchmarker="wrk"        9.89 %         *** 7.341164e-09
 http/simple.js res="setHeaderWH" c=500 chunks=1 length=1024 type="bytes" benchmarker="wrk"        11.74 %         *** 2.112175e-12
 http/simple.js res="setHeaderWH" c=500 chunks=1 length=102400 type="buffer" benchmarker="wrk"      9.05 %         *** 1.937033e-09
 http/simple.js res="setHeaderWH" c=500 chunks=1 length=102400 type="bytes" benchmarker="wrk"       0.78 %             1.559825e-01
 http/simple.js res="setHeaderWH" c=500 chunks=1 length=4 type="buffer" benchmarker="wrk"          10.72 %         *** 4.013310e-10
 http/simple.js res="setHeaderWH" c=500 chunks=1 length=4 type="bytes" benchmarker="wrk"            7.99 %         *** 1.059505e-07
 http/simple.js res="setHeaderWH" c=500 chunks=4 length=1024 type="buffer" benchmarker="wrk"       11.64 %         *** 1.544061e-10
 http/simple.js res="setHeaderWH" c=500 chunks=4 length=1024 type="bytes" benchmarker="wrk"         6.84 %         *** 5.051422e-09
 http/simple.js res="setHeaderWH" c=500 chunks=4 length=102400 type="buffer" benchmarker="wrk"      9.51 %         *** 1.195116e-10
 http/simple.js res="setHeaderWH" c=500 chunks=4 length=102400 type="bytes" benchmarker="wrk"       3.65 %         *** 2.064001e-06
 http/simple.js res="setHeaderWH" c=500 chunks=4 length=4 type="buffer" benchmarker="wrk"          12.36 %         *** 9.105549e-11
 http/simple.js res="setHeaderWH" c=500 chunks=4 length=4 type="bytes" benchmarker="wrk"            6.36 %         *** 6.586488e-07


/cc @nodejs/http
/cc @nodejs/streams for stream changes
CI: https://ci.nodejs.org/job/node-test-pull-request/5651/
CI: https://ci.nodejs.org/job/node-test-pull-request/5652/

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • tests and/or benchmarks are included
  • commit message follows commit guidelines
Affected core subsystem(s)
  • http
  • stream
exports.chunkExpression = /chunk/i;
exports.continueExpression = /100-continue/i;
exports.chunkExpression = /(?:^|\W)chunked(?:$|\W)/i;
exports.continueExpression = /(?:^|\W)100-continue(?:$|\W)/i;

This comment has been minimized.

@mcollina

mcollina Jan 2, 2017

Member

why those changes? are they faster, or safer?

@mcollina

mcollina Jan 2, 2017

Member

why those changes? are they faster, or safer?

This comment has been minimized.

@mscdex

mscdex Jan 2, 2017

Contributor

It's more explicit and therefore at least a little safer and it's consistent with the other regexps we use in _http_server.js when searching header values that can be comma-separated lists.

I did not measure the performance of this particular change on its own.

@mscdex

mscdex Jan 2, 2017

Contributor

It's more explicit and therefore at least a little safer and it's consistent with the other regexps we use in _http_server.js when searching header values that can be comma-separated lists.

I did not measure the performance of this particular change on its own.

this.corkedRequestsFree = new CorkedRequest(this);
var corkReq = { next: null, entry: null, finish: undefined };
corkReq.finish = onCorkedFinish.bind(undefined, corkReq, this);
this.corkedRequestsFree = corkReq;

This comment has been minimized.

@mcollina

mcollina Jan 2, 2017

Member

Is this giving any perf increase? The major benefit is to avoid the creation of CorkedRequest, which was introduced to leverage hidden classes and the like.

@mcollina

mcollina Jan 2, 2017

Member

Is this giving any perf increase? The major benefit is to avoid the creation of CorkedRequest, which was introduced to leverage hidden classes and the like.

This comment has been minimized.

@mscdex

mscdex Jan 2, 2017

Contributor

Yes. This is similar to what was done awhile back for process.nextTick() request objects, changed from new Foo() to plain object.

@mscdex

mscdex Jan 2, 2017

Contributor

Yes. This is similar to what was done awhile back for process.nextTick() request objects, changed from new Foo() to plain object.

Show outdated Hide outdated lib/_stream_writable.js
Show outdated Hide outdated lib/_stream_writable.js
@@ -113,7 +106,9 @@ function WritableState(options, stream) {
// allocate the first CorkedRequest, there is always
// one allocated and free to use, and we maintain at most two
this.corkedRequestsFree = new CorkedRequest(this);
var corkReq = { next: null, entry: null, finish: undefined };
corkReq.finish = onCorkedFinish.bind(undefined, corkReq, this);

This comment has been minimized.

@mcollina

mcollina Jan 2, 2017

Member

can you please update the build script in readable-stream  when this lands too?

@mcollina

mcollina Jan 2, 2017

Member

can you please update the build script in readable-stream  when this lands too?

This comment has been minimized.

@mscdex
@mscdex
@mcollina

LGTM

@@ -129,8 +129,12 @@ function ClientRequest(options, cb) {
self._storeHeader(self.method + ' ' + self.path + ' HTTP/1.1\r\n',
options.headers);
} else if (self.getHeader('expect')) {
if (self._header) {
throw new Error('Can\'t render headers after they are sent to the ' +

This comment has been minimized.

@evanlucas

evanlucas Jan 2, 2017

Member

This additional throw probably makes this PR semver-major?

@evanlucas

evanlucas Jan 2, 2017

Member

This additional throw probably makes this PR semver-major?

This comment has been minimized.

@mscdex

mscdex Jan 2, 2017

Contributor

It shouldn't, I just had to move the check from the old _renderHeaders() to the appropriate call sites since that function no longer exists. I tried just moving it to _storeHeader() but that caused problems IIRC.

@mscdex

mscdex Jan 2, 2017

Contributor

It shouldn't, I just had to move the check from the old _renderHeaders() to the appropriate call sites since that function no longer exists. I tried just moving it to _storeHeader() but that caused problems IIRC.

@@ -218,8 +222,11 @@ ClientRequest.prototype._finish = function _finish() {
};
ClientRequest.prototype._implicitHeader = function _implicitHeader() {
if (this._header) {
throw new Error('Can\'t render headers after they are sent to the client');

This comment has been minimized.

@evanlucas

evanlucas Jan 2, 2017

Member

As does this one

@evanlucas

evanlucas Jan 2, 2017

Member

As does this one

This comment has been minimized.

@mscdex

mscdex Jan 2, 2017

Contributor

It shouldn't, I just had to move the check from the old _renderHeaders() to the appropriate call sites since that function no longer exists. I tried just moving it to _storeHeader() but that caused problems IIRC.

@mscdex

mscdex Jan 2, 2017

Contributor

It shouldn't, I just had to move the check from the old _renderHeaders() to the appropriate call sites since that function no longer exists. I tried just moving it to _storeHeader() but that caused problems IIRC.

var low = false;
while (true) {
switch (field) {
case 'Content-Type':

This comment has been minimized.

@evanlucas

evanlucas Jan 2, 2017

Member

I surprisingly see Content-type and Content-length in the wild a ton. It may be useful to add those as well?

@evanlucas

evanlucas Jan 2, 2017

Member

I surprisingly see Content-type and Content-length in the wild a ton. It may be useful to add those as well?

This comment has been minimized.

@mscdex

mscdex Jan 2, 2017

Contributor

I had to stop somewhere, plus you can only have a switch statement so large before the function gets deopt'ed (I think this may still be the case anyway).

@mscdex

mscdex Jan 2, 2017

Contributor

I had to stop somewhere, plus you can only have a switch statement so large before the function gets deopt'ed (I think this may still be the case anyway).

This comment has been minimized.

@ronkorving

ronkorving Jan 6, 2017

Contributor

Is it not faster (and more elegant imho) to have a lookup object?

@ronkorving

ronkorving Jan 6, 2017

Contributor

Is it not faster (and more elegant imho) to have a lookup object?

This comment has been minimized.

@mscdex

mscdex Jan 6, 2017

Contributor

From my testing it isn't faster, whether with a plain object or Map.

@mscdex

mscdex Jan 6, 2017

Contributor

From my testing it isn't faster, whether with a plain object or Map.

field = entry[0];
value = entry[1];
if (value instanceof Array) {

This comment has been minimized.

@evanlucas

evanlucas Jan 2, 2017

Member

is it safe to use instanceof here?

@evanlucas

evanlucas Jan 2, 2017

Member

is it safe to use instanceof here?

This comment has been minimized.

@mscdex

mscdex Jan 2, 2017

Contributor

It should be, since we're the ones storing header values in this._headers. That's also the reason why we can use for-in instead of Object.keys() (slight speedup there) when iterating over this._headers.

@mscdex

mscdex Jan 2, 2017

Contributor

It should be, since we're the ones storing header values in this._headers. That's also the reason why we can use for-in instead of Object.keys() (slight speedup there) when iterating over this._headers.

@@ -388,7 +419,10 @@ OutgoingMessage.prototype.getHeader = function getHeader(name) {
if (!this._headers) return;
return this._headers[name.toLowerCase()];
var entry = this._headers[name.toLowerCase()];

This comment has been minimized.

@evanlucas

evanlucas Jan 2, 2017

Member

should we not use similar logic as in matchKnownFields here?

@evanlucas

evanlucas Jan 2, 2017

Member

should we not use similar logic as in matchKnownFields here?

This comment has been minimized.

@mscdex

mscdex Jan 2, 2017

Contributor

I don't recall specifically if I tested it in here or not, but in some places such functions didn't seem to perform as well for whatever reason.

@mscdex

mscdex Jan 2, 2017

Contributor

I don't recall specifically if I tested it in here or not, but in some places such functions didn't seem to perform as well for whatever reason.

if (obj) {
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++) {
var k = keys[i];
k = keys[i];

This comment has been minimized.

@evanlucas

evanlucas Jan 2, 2017

Member

did this change actually make a perf impact?

@evanlucas

evanlucas Jan 2, 2017

Member

did this change actually make a perf impact?

This comment has been minimized.

@mscdex

mscdex Jan 2, 2017

Contributor

It wasn't about performance but easier readability and because I check if the loop was entered below by checking k.

@mscdex

mscdex Jan 2, 2017

Contributor

It wasn't about performance but easier readability and because I check if the loop was entered below by checking k.

This comment has been minimized.

@evanlucas

evanlucas Jan 11, 2017

Member

ah ok, that makes sense

@evanlucas

evanlucas Jan 11, 2017

Member

ah ok, that makes sense

var fixed = 'C'.repeat(20 * 1024);
var storedBytes = Object.create(null);
var storedBuffer = Object.create(null);
var storedUnicode = Object.create(null);

This comment has been minimized.

@Fishrock123

Fishrock123 Jan 3, 2017

Member

Can these be Maps instead? Also, let?

@Fishrock123

Fishrock123 Jan 3, 2017

Member

Can these be Maps instead? Also, let?

This comment has been minimized.

@mscdex

mscdex Jan 3, 2017

Contributor

AFAIK Map is still slow and http benchmarks already take a very long time as it is.

As far as converting to ES6 goes, that's for a separate PR I think. All I was doing in this part here was the changing style.

@mscdex

mscdex Jan 3, 2017

Contributor

AFAIK Map is still slow and http benchmarks already take a very long time as it is.

As far as converting to ES6 goes, that's for a separate PR I think. All I was doing in this part here was the changing style.

This comment has been minimized.

@Fishrock123

Fishrock123 Jan 3, 2017

Member

AFAIK Map is still slow and http benchmarks already take a very long time as it is.

That is why we have https://github.com/nodejs/node/blob/master/benchmark/es/map-bench.js - tl;dr, it's faster.

@Fishrock123

Fishrock123 Jan 3, 2017

Member

AFAIK Map is still slow and http benchmarks already take a very long time as it is.

That is why we have https://github.com/nodejs/node/blob/master/benchmark/es/map-bench.js - tl;dr, it's faster.

This comment has been minimized.

@jasnell

jasnell Jan 3, 2017

Member

Map performance definitely appears to have improved significantly as of late.

@jasnell

jasnell Jan 3, 2017

Member

Map performance definitely appears to have improved significantly as of late.

This comment has been minimized.

@mscdex

mscdex Jan 3, 2017

Contributor

Right, but I seem to recall some issue with that benchmark. I think there was discussion in some issue/PR awhile ago about it?

@mscdex

mscdex Jan 3, 2017

Contributor

Right, but I seem to recall some issue with that benchmark. I think there was discussion in some issue/PR awhile ago about it?

@jasnell

This comment has been minimized.

Show comment
Hide comment
@jasnell

jasnell Jan 5, 2017

Member

@mscdex ... looks like this needs a rebase

Member

jasnell commented Jan 5, 2017

@mscdex ... looks like this needs a rebase

@mscdex

This comment has been minimized.

Show comment
Hide comment
Contributor

mscdex commented Jan 5, 2017

@mscdex

This comment has been minimized.

Show comment
Hide comment
@mscdex

mscdex Jan 6, 2017

Contributor

@nodejs/collaborators Any other comments/suggestions/approvals?

Contributor

mscdex commented Jan 6, 2017

@nodejs/collaborators Any other comments/suggestions/approvals?

@jasnell

jasnell approved these changes Jan 6, 2017

@mscdex

This comment has been minimized.

Show comment
Hide comment
@mscdex

mscdex Jan 8, 2017

Contributor

@evanlucas Did I sufficiently answer your questions? If so, does this LGTY?

Contributor

mscdex commented Jan 8, 2017

@evanlucas Did I sufficiently answer your questions? If so, does this LGTY?

@evanlucas

LGTM

if (obj) {
var keys = Object.keys(obj);
for (var i = 0; i < keys.length; i++) {
var k = keys[i];
k = keys[i];

This comment has been minimized.

@evanlucas

evanlucas Jan 11, 2017

Member

ah ok, that makes sense

@evanlucas

evanlucas Jan 11, 2017

Member

ah ok, that makes sense

@mscdex

This comment has been minimized.

Show comment
Hide comment
@mscdex

mscdex Jan 11, 2017

Contributor

CI one last time before landing: https://ci.nodejs.org/job/node-test-pull-request/5812/

EDIT: all green except for a flaky test on OSX.

Contributor

mscdex commented Jan 11, 2017

CI one last time before landing: https://ci.nodejs.org/job/node-test-pull-request/5812/

EDIT: all green except for a flaky test on OSX.

mscdex added some commits Dec 31, 2016

benchmark: add http header setting scenarios
PR-URL: #10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
http: check statusCode early
By enforcing the statusCode to be an SMI, it helps a bit
performance-wise when looking up the associated statusMessage.

PR-URL: #10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
http: optimize header storage and matching
This commit implements two optimizations when working with headers:

* Avoid having to explicitly "render" headers and separately store the
original casing for header names.

* Match special header names using a single regular expression instead
of testing one regular expression per header name.

PR-URL: #10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
http: avoid using object for removed header status
PR-URL: #10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
http: try to avoid lowercasing incoming headers
PR-URL: #10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
http: misc optimizations and style fixes
PR-URL: #10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
benchmark: allow zero when parsing http req/s
Without this, the http benchmarker would report "strange output" if
wrk or any other http client reported 0 requests per second, which is
a valid result.

PR-URL: #10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
stream: use plain objects for write/corked reqs
This is similar to a change made awhile back for storing
process.nextTick() requests.

PR-URL: #10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
stream: avoid instanceof
PR-URL: #10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>

@mscdex mscdex merged commit 03b9f6f into nodejs:master Jan 11, 2017

@mscdex mscdex deleted the mscdex:http-perf branch Jan 11, 2017

@mscdex

This comment has been minimized.

Show comment
Hide comment
@mscdex

mscdex Jan 13, 2017

Contributor

/cc @nodejs/ctc

I'm now marking this as semver-major because I just realized I forgot to run citgm and I just found out that there are apparently users (at least on github) that are using res._headerNames without checking its value first and/or making assumptions about the property values on res._headers, both of which changed in this PR.

So far the only instance on citgm where I ran into this is express, which uses the fresh module which makes assumptions about res._headers values. I will be submitting a PR to that project ASAP (EDIT: jshttp/fresh#20).

@ChALkeR Could you find out how many other modules on npm may be affected?

I really apologize for all of this....

Contributor

mscdex commented Jan 13, 2017

/cc @nodejs/ctc

I'm now marking this as semver-major because I just realized I forgot to run citgm and I just found out that there are apparently users (at least on github) that are using res._headerNames without checking its value first and/or making assumptions about the property values on res._headers, both of which changed in this PR.

So far the only instance on citgm where I ran into this is express, which uses the fresh module which makes assumptions about res._headers values. I will be submitting a PR to that project ASAP (EDIT: jshttp/fresh#20).

@ChALkeR Could you find out how many other modules on npm may be affected?

I really apologize for all of this....

@mscdex

This comment has been minimized.

Show comment
Hide comment
@mscdex

mscdex Jan 14, 2017

Contributor

I've now submitted a PR that should help resolve the main use cases for end users accessing ._headers in the first place: #10805

Since IIRC we don't have an official policy on undocumented, "private" (underscore-prefixed) properties yet, it would be good to hear what others think should be the way forward on this. Some ideas:

  • Land #10805 and backport it to the LTS branches ASAP and this PR is only included in node v8.0.0+.
  • Temporarily revert the changes to ._headers for one full major version to give users more time to convert over to the .getHeaders() API. This means the re-landing of the original changes would happen in node v9.0.0. This solution would probably require us to really get the word out if there is as much possible breakage as there may seem to be.
  • Switch the current ._headers to some other name and make ._headers a getter that results in a deprecation warning (directing them to .getHeaders()) but still returns the value using the new property. This might make it less semver-major-y and would probably cause less breakage.

As far as the now removed ._headerNames goes, we could do like option 3 above and re-add it as a getter that results in a deprecation warning but still returns the original cased name now stored in ._headers. However I don't know if using getters like this would break anyone still or not (again, it's also an undocumented, "private" property, so how much do we care?) or at least to a lesser degree. Also, I am going to go out on a limb and say that ._headerNames usage is probably much less than ._headers usage in the wild.

Contributor

mscdex commented Jan 14, 2017

I've now submitted a PR that should help resolve the main use cases for end users accessing ._headers in the first place: #10805

Since IIRC we don't have an official policy on undocumented, "private" (underscore-prefixed) properties yet, it would be good to hear what others think should be the way forward on this. Some ideas:

  • Land #10805 and backport it to the LTS branches ASAP and this PR is only included in node v8.0.0+.
  • Temporarily revert the changes to ._headers for one full major version to give users more time to convert over to the .getHeaders() API. This means the re-landing of the original changes would happen in node v9.0.0. This solution would probably require us to really get the word out if there is as much possible breakage as there may seem to be.
  • Switch the current ._headers to some other name and make ._headers a getter that results in a deprecation warning (directing them to .getHeaders()) but still returns the value using the new property. This might make it less semver-major-y and would probably cause less breakage.

As far as the now removed ._headerNames goes, we could do like option 3 above and re-add it as a getter that results in a deprecation warning but still returns the original cased name now stored in ._headers. However I don't know if using getters like this would break anyone still or not (again, it's also an undocumented, "private" property, so how much do we care?) or at least to a lesser degree. Also, I am going to go out on a limb and say that ._headerNames usage is probably much less than ._headers usage in the wild.

@evanlucas

This comment has been minimized.

Show comment
Hide comment
@evanlucas

evanlucas Jan 14, 2017

Member

considering that fresh was downloaded 309,483 times in the last day, I think we should revert (quickly) and then re-evaluate. I would think that there are way too many people depending on older versions of express for us to revert this.

Member

evanlucas commented Jan 14, 2017

considering that fresh was downloaded 309,483 times in the last day, I think we should revert (quickly) and then re-evaluate. I would think that there are way too many people depending on older versions of express for us to revert this.

@mcollina mcollina referenced this pull request Jan 16, 2017

Merged

http: add new functions to OutgoingMessage #10805

4 of 4 tasks complete

italoacasas added a commit to italoacasas/node that referenced this pull request Jan 18, 2017

benchmark: add http header setting scenarios
PR-URL: nodejs#10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>

italoacasas added a commit to italoacasas/node that referenced this pull request Jan 18, 2017

http: check statusCode early
By enforcing the statusCode to be an SMI, it helps a bit
performance-wise when looking up the associated statusMessage.

PR-URL: nodejs#10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>

italoacasas added a commit to italoacasas/node that referenced this pull request Jan 18, 2017

http: optimize header storage and matching
This commit implements two optimizations when working with headers:

* Avoid having to explicitly "render" headers and separately store the
original casing for header names.

* Match special header names using a single regular expression instead
of testing one regular expression per header name.

PR-URL: nodejs#10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>

italoacasas added a commit to italoacasas/node that referenced this pull request Jan 18, 2017

http: avoid using object for removed header status
PR-URL: nodejs#10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>

italoacasas added a commit to italoacasas/node that referenced this pull request Jan 18, 2017

http: try to avoid lowercasing incoming headers
PR-URL: nodejs#10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>

italoacasas added a commit to italoacasas/node that referenced this pull request Jan 18, 2017

http: misc optimizations and style fixes
PR-URL: nodejs#10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>

italoacasas added a commit to italoacasas/node that referenced this pull request Jan 18, 2017

benchmark: allow zero when parsing http req/s
Without this, the http benchmarker would report "strange output" if
wrk or any other http client reported 0 requests per second, which is
a valid result.

PR-URL: nodejs#10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>

italoacasas added a commit to italoacasas/node that referenced this pull request Jan 18, 2017

stream: use plain objects for write/corked reqs
This is similar to a change made awhile back for storing
process.nextTick() requests.

PR-URL: nodejs#10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>

italoacasas added a commit to italoacasas/node that referenced this pull request Jan 18, 2017

stream: avoid instanceof
PR-URL: nodejs#10558
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Evan Lucas <evanlucas@me.com>
@mscdex

This comment has been minimized.

Show comment
Hide comment
@mscdex

mscdex Jan 20, 2017

Contributor

Any feedback from additional @nodejs/ctc members? Especially on any of the solutions I've proposed?

Contributor

mscdex commented Jan 20, 2017

Any feedback from additional @nodejs/ctc members? Especially on any of the solutions I've proposed?

@bnoordhuis

This comment has been minimized.

Show comment
Hide comment
@bnoordhuis

bnoordhuis Jan 20, 2017

Member

Switch the current ._headers to some other name and make ._headers a getter that results in a deprecation warning (directing them to .getHeaders()) but still returns the value using the new property.

That sounds like a nice enough solution. Warn in v8.x and remove in v9.x?

Member

bnoordhuis commented Jan 20, 2017

Switch the current ._headers to some other name and make ._headers a getter that results in a deprecation warning (directing them to .getHeaders()) but still returns the value using the new property.

That sounds like a nice enough solution. Warn in v8.x and remove in v9.x?

@dougwilson

This comment has been minimized.

Show comment
Hide comment
@dougwilson

dougwilson Jan 21, 2017

Member

So to give a little detail here from Express side, the ._headers usage in Express is mainly used in the conditional response logic, and it's location is at the heart of the Express code paths for almost every version of Express ever released so far. I would venture to guess almost every Express app out there is running over this code path.

@mscdex made some PRs and we are working to iron out some edge cases, but when Express does release a version that does not reference ._headers there is certainly many years of versions out there that do. I can say from user support that it is very common for people not to be using the latest version of Express, even when the latest version has been out for over half a year, but I don't really know what percentage of those users end up on a new version of Express.

My thoughts are that if 8.x is going to become the next LTS, it would be really nice if the warning / removal started in a non-LTS version based on the rate it seems people upgrade Express. From the past, even a warning will end up having a lot of fallout from confused users all over the place, so just brainstorming how can we have the best chance for the change to go out unnoticed by the vast majority of the users.

Member

dougwilson commented Jan 21, 2017

So to give a little detail here from Express side, the ._headers usage in Express is mainly used in the conditional response logic, and it's location is at the heart of the Express code paths for almost every version of Express ever released so far. I would venture to guess almost every Express app out there is running over this code path.

@mscdex made some PRs and we are working to iron out some edge cases, but when Express does release a version that does not reference ._headers there is certainly many years of versions out there that do. I can say from user support that it is very common for people not to be using the latest version of Express, even when the latest version has been out for over half a year, but I don't really know what percentage of those users end up on a new version of Express.

My thoughts are that if 8.x is going to become the next LTS, it would be really nice if the warning / removal started in a non-LTS version based on the rate it seems people upgrade Express. From the past, even a warning will end up having a lot of fallout from confused users all over the place, so just brainstorming how can we have the best chance for the change to go out unnoticed by the vast majority of the users.

@mscdex mscdex referenced this pull request Jan 21, 2017

Merged

http: add doc deprecation for private props #10941

3 of 3 tasks complete
@mscdex

This comment has been minimized.

Show comment
Hide comment
@mscdex

mscdex Jan 21, 2017

Contributor

Alright, I have proposed a getter-based solution in #10941.

Contributor

mscdex commented Jan 21, 2017

Alright, I have proposed a getter-based solution in #10941.

@evanlucas

This comment has been minimized.

Show comment
Hide comment
@evanlucas

evanlucas Feb 20, 2017

Member

I am still +1 for reverting fwiw. I think we need to investigate better how this impacts the ecosystem especially considering that citgm is broken with this change...

Member

evanlucas commented Feb 20, 2017

I am still +1 for reverting fwiw. I think we need to investigate better how this impacts the ecosystem especially considering that citgm is broken with this change...

@mscdex

This comment has been minimized.

Show comment
Hide comment
@mscdex

mscdex Feb 20, 2017

Contributor

@evanlucas If at least one other @nodejs/ctc member LGTM's #10941 then it shouldn't be an issue anymore.

Contributor

mscdex commented Feb 20, 2017

@evanlucas If at least one other @nodejs/ctc member LGTM's #10941 then it shouldn't be an issue anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment