• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1'use strict';
2
3// Test to validate massive dns lookups do not block filesytem I/O
4// (or any fast I/O). Prior to https://github.com/libuv/libuv/pull/1845
5// few back-to-back dns lookups were sufficient to engage libuv
6// threadpool workers in a blocking manner, throttling other work items
7// that need pool resources. Start slow and fast I/Os together, make sure
8// fast I/O can complete in at least in 1/100th of time for slow I/O.
9// TEST TIME TO COMPLETION: ~5 seconds.
10
11const common = require('../common');
12const dns = require('dns');
13const fs = require('fs');
14const assert = require('assert');
15
16const start = Date.now();
17
18const slowIOmax = 100;
19let slowIOcount = 0;
20let fastIOdone = false;
21let slowIOend, fastIOend;
22
23function onResolve() {
24  slowIOcount++;
25  if (slowIOcount === slowIOmax) {
26    slowIOend = Date.now();
27
28    // Conservative expectation: finish disc I/O
29    // at least by when the net I/O completes.
30    assert.ok(fastIOdone,
31              'fast I/O was throttled due to threadpool congestion.');
32
33    // More realistic expectation: finish disc I/O at least within
34    // a time duration that is half of net I/O.
35    // Ideally the slow I/O should not affect the fast I/O as those
36    // have two different thread-pool buckets. However, this could be
37    // highly load / platform dependent, so don't be very greedy.
38    const fastIOtime = fastIOend - start;
39    const slowIOtime = slowIOend - start;
40    const expectedMax = slowIOtime / 2;
41    assert.ok(fastIOtime < expectedMax,
42              'fast I/O took longer to complete, ' +
43              `actual: ${fastIOtime}, expected: ${expectedMax}`);
44  }
45}
46
47
48for (let i = 0; i < slowIOmax; i++) {
49  // We need to refresh the domain string everytime,
50  // otherwise the TCP stack that cache the previous lookup
51  // returns result from memory, breaking all our Math.
52  dns.lookup(`${randomDomain()}.com`, {}, common.mustCall(onResolve));
53}
54
55fs.readFile(__filename, common.mustCall(() => {
56  fastIOend = Date.now();
57  fastIOdone = true;
58}));
59
60function randomDomain() {
61  const d = Buffer.alloc(10);
62  for (let i = 0; i < 10; i++)
63    d[i] = 97 + (Math.round(Math.random() * 13247)) % 26;
64  return d.toString();
65}
66