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

http2: improve compat performance #25567

Closed
wants to merge 1 commit into from

Conversation

mcollina
Copy link
Member

@mcollina mcollina commented Jan 18, 2019

This bunch of commits help me improve the performance of a http2
server by 8-10%. The benchmarks reports several 1-2% improvements in
various areas.

Benchmarks
                                                                                   confidence improvement accuracy (*)    (**)   (***)
 http2/compat.js benchmarker='h2load' clients=2 streams=1 requests=100                             0.33 %       ±0.99%  ±1.31%  ±1.71%
 http2/compat.js benchmarker='h2load' clients=2 streams=1 requests=1000                           -0.28 %       ±0.81%  ±1.08%  ±1.41%
 http2/compat.js benchmarker='h2load' clients=2 streams=1 requests=5000                            0.69 %       ±2.06%  ±2.74%  ±3.56%
 http2/compat.js benchmarker='h2load' clients=2 streams=10 requests=100                            0.64 %       ±0.91%  ±1.22%  ±1.58%
 http2/compat.js benchmarker='h2load' clients=2 streams=10 requests=1000                           0.60 %       ±1.06%  ±1.41%  ±1.84%
 http2/compat.js benchmarker='h2load' clients=2 streams=10 requests=5000                           0.76 %       ±1.43%  ±1.91%  ±2.49%
 http2/compat.js benchmarker='h2load' clients=2 streams=100 requests=100                           3.03 %       ±9.95% ±13.24% ±17.24%
 http2/compat.js benchmarker='h2load' clients=2 streams=100 requests=1000                          0.39 %       ±3.41%  ±4.54%  ±5.91%
 http2/compat.js benchmarker='h2load' clients=2 streams=100 requests=5000                   *      1.76 %       ±1.56%  ±2.08%  ±2.70%
 http2/compat.js benchmarker='h2load' clients=2 streams=20 requests=100                            2.31 %       ±4.51%  ±6.00%  ±7.82%
 http2/compat.js benchmarker='h2load' clients=2 streams=20 requests=1000                          -0.06 %       ±1.77%  ±2.36%  ±3.07%
 http2/compat.js benchmarker='h2load' clients=2 streams=20 requests=5000                           0.02 %       ±2.14%  ±2.85%  ±3.72%
 http2/compat.js benchmarker='h2load' clients=2 streams=200 requests=100                           6.43 %       ±9.24% ±12.30% ±16.01%
 http2/compat.js benchmarker='h2load' clients=2 streams=200 requests=1000                          1.73 %       ±2.94%  ±3.92%  ±5.10%
 http2/compat.js benchmarker='h2load' clients=2 streams=200 requests=5000                          1.11 %       ±1.64%  ±2.18%  ±2.84%
 http2/compat.js benchmarker='h2load' clients=2 streams=40 requests=100                            5.04 %       ±8.48% ±11.29% ±14.72%
 http2/compat.js benchmarker='h2load' clients=2 streams=40 requests=1000                          -1.15 %       ±2.79%  ±3.72%  ±4.84%
 http2/compat.js benchmarker='h2load' clients=2 streams=40 requests=5000                          -0.55 %       ±1.93%  ±2.56%  ±3.34%
 http2/headers.js nheaders=0 n=1000                                                               -0.08 %       ±0.80%  ±1.07%  ±1.39%
 http2/headers.js nheaders=10 n=1000                                                              -0.41 %       ±0.58%  ±0.78%  ±1.01%
 http2/headers.js nheaders=100 n=1000                                                             -0.26 %       ±0.51%  ±0.67%  ±0.88%
 http2/headers.js nheaders=1000 n=1000                                                            -0.15 %       ±0.24%  ±0.32%  ±0.42%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=1 requests=100             *      2.44 %       ±2.03%  ±2.70%  ±3.52%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=1 requests=1000                   0.22 %       ±1.73%  ±2.30%  ±3.00%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=1 requests=5000                   0.54 %       ±1.61%  ±2.14%  ±2.79%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=10 requests=100                   0.15 %       ±1.41%  ±1.87%  ±2.44%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=10 requests=1000                 -0.15 %       ±1.45%  ±1.94%  ±2.54%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=10 requests=5000                  0.46 %       ±0.82%  ±1.09%  ±1.42%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=100 requests=100         ***      1.87 %       ±1.01%  ±1.35%  ±1.76%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=100 requests=1000          *      1.26 %       ±1.25%  ±1.67%  ±2.17%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=100 requests=5000                -0.52 %       ±1.32%  ±1.76%  ±2.29%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=20 requests=100                   0.03 %       ±0.74%  ±0.98%  ±1.28%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=20 requests=1000                  0.28 %       ±0.85%  ±1.14%  ±1.48%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=20 requests=5000                 -0.09 %       ±0.81%  ±1.08%  ±1.41%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=200 requests=100           *      1.24 %       ±1.10%  ±1.46%  ±1.90%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=200 requests=1000                -0.47 %       ±1.28%  ±1.70%  ±2.22%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=200 requests=5000          *      1.16 %       ±1.14%  ±1.51%  ±1.97%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=40 requests=100                  -0.86 %       ±0.93%  ±1.24%  ±1.62%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=40 requests=1000                  0.06 %       ±1.12%  ±1.49%  ±1.95%
 http2/respond-with-fd.js benchmarker='h2load' clients=2 streams=40 requests=5000         ***      1.22 %       ±0.52%  ±0.69%  ±0.90%
 http2/simple.js benchmarker='h2load' clients=2 streams=1 requests=100                      *     -0.91 %       ±0.73%  ±0.97%  ±1.27%
 http2/simple.js benchmarker='h2load' clients=2 streams=1 requests=1000                           -0.53 %       ±1.23%  ±1.64%  ±2.14%
 http2/simple.js benchmarker='h2load' clients=2 streams=1 requests=5000                            1.49 %       ±2.06%  ±2.74%  ±3.57%
 http2/simple.js benchmarker='h2load' clients=2 streams=10 requests=100                     *      0.99 %       ±0.90%  ±1.20%  ±1.57%
 http2/simple.js benchmarker='h2load' clients=2 streams=10 requests=1000                           0.64 %       ±1.10%  ±1.46%  ±1.90%
 http2/simple.js benchmarker='h2load' clients=2 streams=10 requests=5000                           1.19 %       ±1.34%  ±1.78%  ±2.31%
 http2/simple.js benchmarker='h2load' clients=2 streams=100 requests=100                           2.60 %       ±9.65% ±12.85% ±16.74%
 http2/simple.js benchmarker='h2load' clients=2 streams=100 requests=1000                          0.19 %       ±2.91%  ±3.87%  ±5.04%
 http2/simple.js benchmarker='h2load' clients=2 streams=100 requests=5000                          1.13 %       ±1.93%  ±2.57%  ±3.35%
 http2/simple.js benchmarker='h2load' clients=2 streams=20 requests=100                            1.03 %       ±2.41%  ±3.21%  ±4.19%
 http2/simple.js benchmarker='h2load' clients=2 streams=20 requests=1000                          -0.14 %       ±1.08%  ±1.43%  ±1.87%
 http2/simple.js benchmarker='h2load' clients=2 streams=20 requests=5000                           1.10 %       ±1.40%  ±1.86%  ±2.42%
 http2/simple.js benchmarker='h2load' clients=2 streams=200 requests=100                           1.81 %      ±10.09% ±13.43% ±17.48%
 http2/simple.js benchmarker='h2load' clients=2 streams=200 requests=1000                         -1.01 %       ±3.39%  ±4.51%  ±5.87%
 http2/simple.js benchmarker='h2load' clients=2 streams=200 requests=5000                         -0.43 %       ±1.72%  ±2.29%  ±2.98%
 http2/simple.js benchmarker='h2load' clients=2 streams=40 requests=100                            7.06 %       ±8.88% ±11.83% ±15.42%
 http2/simple.js benchmarker='h2load' clients=2 streams=40 requests=1000                           1.38 %       ±2.88%  ±3.83%  ±4.98%
 http2/simple.js benchmarker='h2load' clients=2 streams=40 requests=5000                           0.75 %       ±1.74%  ±2.32%  ±3.02%
 http2/write.js benchmarker='h2load' size=100000 length=1048576 streams=100                        0.16 %       ±0.22%  ±0.30%  ±0.39%
 http2/write.js benchmarker='h2load' size=100000 length=1048576 streams=1000                       0.16 %       ±0.34%  ±0.45%  ±0.58%
 http2/write.js benchmarker='h2load' size=100000 length=1048576 streams=200                        0.12 %       ±0.18%  ±0.24%  ±0.31%
 http2/write.js benchmarker='h2load' size=100000 length=131072 streams=100                         0.86 %       ±1.54%  ±2.05%  ±2.68%
 http2/write.js benchmarker='h2load' size=100000 length=131072 streams=1000                        0.35 %       ±2.25%  ±2.99%  ±3.90%
 http2/write.js benchmarker='h2load' size=100000 length=131072 streams=200                         0.26 %       ±1.88%  ±2.50%  ±3.26%
 http2/write.js benchmarker='h2load' size=100000 length=262144 streams=100                         0.03 %       ±1.73%  ±2.31%  ±3.00%
 http2/write.js benchmarker='h2load' size=100000 length=262144 streams=1000                       -0.40 %       ±1.84%  ±2.45%  ±3.19%
 http2/write.js benchmarker='h2load' size=100000 length=262144 streams=200                         1.58 %       ±1.73%  ±2.31%  ±3.00%
 http2/write.js benchmarker='h2load' size=100000 length=65536 streams=100                         -0.06 %       ±0.75%  ±1.00%  ±1.31%
 http2/write.js benchmarker='h2load' size=100000 length=65536 streams=1000                         0.69 %       ±0.85%  ±1.14%  ±1.48%
 http2/write.js benchmarker='h2load' size=100000 length=65536 streams=200                          0.71 %       ±0.77%  ±1.03%  ±1.34%
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 the lib / src Issues and PRs related to general changes in the lib or src directory. label Jan 18, 2019
sw->InstanceTemplate()->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "callback"),
v8::Null(env->isolate()));
sw->InstanceTemplate()->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "handle"),
v8::Null(env->isolate()));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bmeurer could you review this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @bmeurer!

@addaleax we might want to do this trick in other places as well (WriteWrap).

This bunch of commits help me improve the performance of a http2
server by 8-10%. The benchmarks reports several 1-2% improvements in
various areas.
Copy link
Member

@bmeurer bmeurer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense (although I have to admit that I don't have the full context on everything).


if (oldHeaders !== null && oldHeaders !== undefined) {
const hop = hasOwnProperty.bind(oldHeaders);
// This loop is here for performance reason. Do not change.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a comment referring to the benchmark that is the reason for “Do not change” (or instead of it)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In frankness I can't. I've added the comment because I saw these types of loops being removed from other critical places. They shouldn't unless there is a key reason to do so.

Our benchmarks do not cover why the previous case were slower, and I struggled in creating one.

'use strict'

const fastify = require('fastify')({
  http2: true
})

fastify
  .get('/', function (req, reply) {
    reply.send({})
  })

fastify.listen(3000, err => {
  if (err) throw err
  console.log(`server listening on ${fastify.server.address().port}`)
})

I used this command:

h2load -c 1 -m 100 -D 10 http://localhost:3000

I'm getting 49k req/sec vs 45k req/sec between this PR and master.
(Note that each of the changes matters for a bit of the improvement and taken alone are hard to measure).

@@ -499,12 +501,12 @@ class NghttpError extends Error {
}
}

function assertIsObject(value, name, types = 'Object') {
function assertIsObject(value, name, types) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/cc @nodejs/v8 Is it a know issue that default parameters are slow?

@danbev
Copy link
Contributor

danbev commented Jan 23, 2019

CI: https://ci.nodejs.org/job/node-test-pull-request/20278/ (:white_check_mark:)

@danbev
Copy link
Contributor

danbev commented Feb 11, 2019

Landed in 9af04ad.

@danbev danbev closed this Feb 11, 2019
danbev pushed a commit that referenced this pull request Feb 11, 2019
This bunch of commits help me improve the performance of a http2
server by 8-10%. The benchmarks reports several 1-2% improvements in
various areas.

PR-URL: #25567
Reviewed-By: Benedikt Meurer <benedikt.meurer@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
targos pushed a commit that referenced this pull request Feb 11, 2019
This bunch of commits help me improve the performance of a http2
server by 8-10%. The benchmarks reports several 1-2% improvements in
various areas.

PR-URL: #25567
Reviewed-By: Benedikt Meurer <benedikt.meurer@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: James M Snell <jasnell@gmail.com>
assertIsObject(oldHeaders, 'headers');
const headers = Object.create(null);

if (oldHeaders !== null && oldHeaders !== undefined) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assertIsObject above makes this if useless

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.

8 participants