| 'use strict'; |
| |
| // Test to validate massive dns lookups do not block filesytem I/O |
| // (or any fast I/O). Prior to https://github.com/libuv/libuv/pull/1845 |
| // few back-to-back dns lookups were sufficient to engage libuv |
| // threadpool workers in a blocking manner, throttling other work items |
| // that need pool resources. Start slow and fast I/Os together, make sure |
| // fast I/O can complete in at least in 1/100th of time for slow I/O. |
| // TEST TIME TO COMPLETION: ~5 seconds. |
| |
| const common = require('../common'); |
| const dns = require('dns'); |
| const fs = require('fs'); |
| const assert = require('assert'); |
| |
| const start = Date.now(); |
| |
| const slowIOmax = 100; |
| let slowIOcount = 0; |
| let fastIOdone = false; |
| let slowIOend, fastIOend; |
| |
| function onResolve() { |
| slowIOcount++; |
| if (slowIOcount === slowIOmax) { |
| slowIOend = Date.now(); |
| |
| // Conservative expectation: finish disc I/O |
| // at least by when the net I/O completes. |
| assert.ok(fastIOdone, |
| 'fast I/O was throttled due to threadpool congestion.'); |
| |
| // More realistic expectation: finish disc I/O at least within |
| // a time duration that is half of net I/O. |
| // Ideally the slow I/O should not affect the fast I/O as those |
| // have two different thread-pool buckets. However, this could be |
| // highly load / platform dependent, so don't be very greedy. |
| const fastIOtime = fastIOend - start; |
| const slowIOtime = slowIOend - start; |
| const expectedMax = slowIOtime / 2; |
| assert.ok(fastIOtime < expectedMax, |
| 'fast I/O took longer to complete, ' + |
| `actual: ${fastIOtime}, expected: ${expectedMax}`); |
| } |
| } |
| |
| |
| for (let i = 0; i < slowIOmax; i++) { |
| // We need to refresh the domain string everytime, |
| // otherwise the TCP stack that cache the previous lookup |
| // returns result from memory, breaking all our Math. |
| dns.lookup(`${randomDomain()}.com`, {}, common.mustCall(onResolve)); |
| } |
| |
| fs.readFile(__filename, common.mustCall(() => { |
| fastIOend = Date.now(); |
| fastIOdone = true; |
| })); |
| |
| function randomDomain() { |
| const d = Buffer.alloc(10); |
| for (let i = 0; i < 10; i++) |
| d[i] = 97 + (Math.round(Math.random() * 13247)) % 26; |
| return d.toString(); |
| } |