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

parallel requests don't scale #85

Closed
stefan-guggisberg opened this issue Feb 25, 2020 · 5 comments
Closed

parallel requests don't scale #85

stefan-guggisberg opened this issue Feb 25, 2020 · 5 comments
Labels

Comments

@stefan-guggisberg
Copy link
Contributor

stefan-guggisberg commented Feb 25, 2020

When running parallel requests to the same http2 origin the total time roughly increases linearly with the number of requests.

test.js

const { fetch } = require('fetch-h2');
//const fetch = require('node-fetch-h2');

var args = process.argv.slice(2);
const N = args.length && !isNaN(parseInt(args[0])) ? parseInt(args[0]) : 100;

console.log(`running ${N} paralled requests...`)

const TEST_URL = 'https://httpbin.org/bytes/'; // HTTP2

(async function () {
  // generete array of 'randomized' urls
  const urls = Array.from({ length: N }, () => Math.floor(Math.random() * N)).map((num) => `${TEST_URL}${num}`);

  // establish initial connection
  // (workround for https://github.com/grantila/fetch-h2/issues/39)
  await (await fetch(`${TEST_URL}${N}`)).arrayBuffer();

  const ts0 = Date.now();

  // send requests
  const responses = await Promise.all(urls.map((url) => fetch(url)));

  // read bodies
  await Promise.all(responses.map((resp) => resp.arrayBuffer()));

  const ok = responses.filter((res) => res.ok);
  if (ok.length !== N) {
    console.log(`failed requests: ${N - ok.length}`);
  }

  const ts1 = Date.now();

  console.log(`Elapsed time: ${ts1 - ts0} ms`);
}());

node test.js 10 takes ~1s
node test.js 100 takes ~10s
node test.js 200 takes ~20s

Note that the included workaround for #39 (send an initial blocking request) doesn't have a significant impact on the results.

OTOH, when running the same tests with node-fetch-h2 instead of fetch-h2:

node test.js 10 takes ~200ms
node test.js 100 takes ~300ms
node test.js 200 takes ~500ms

There seems to be a massive bottleneck in fetch-h2 responsible for the poor performance.

@stefan-guggisberg
Copy link
Contributor Author

stefan-guggisberg commented Mar 10, 2020

My guess: It's either an issue with already#funnel itself or how (and where) funnel is used in fetch-h2. It seems like parallel requests to the same HTTP/2 endpoint are effectively serialised, which IMO defeats the purpose.

@stefan-guggisberg
Copy link
Contributor Author

@grantila I'd appreciate your comments.

@grantila
Copy link
Owner

Thanks, yes this is obviously not good and a serious bug. I'm looking into it.

@github-actions
Copy link

🎉 This issue has been resolved in version 2.4.3 🎉

The release is available on:

Your semantic-release bot 📦🚀

@stefan-guggisberg
Copy link
Contributor Author

@grantila Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants