From bc9e25f020900b17960924bed5269a7f8ae2d820 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vin=C3=ADcius=20Louren=C3=A7o?= Date: Wed, 4 Oct 2023 08:18:40 -0300 Subject: [PATCH 1/5] benchmark: fix race condition on fs benchs --- benchmark/fs/readfile-partitioned.js | 16 +++++++++++----- benchmark/fs/readfile-permission-enabled.js | 18 ++++++++++++------ benchmark/fs/readfile-promises.js | 18 ++++++++++++------ benchmark/fs/readfile.js | 18 ++++++++++++------ benchmark/fs/writefile-promises.js | 20 +++++++++++++------- 5 files changed, 60 insertions(+), 30 deletions(-) diff --git a/benchmark/fs/readfile-partitioned.js b/benchmark/fs/readfile-partitioned.js index b0183709e9f1e9..2c3af9614c3d2f 100644 --- a/benchmark/fs/readfile-partitioned.js +++ b/benchmark/fs/readfile-partitioned.js @@ -43,11 +43,17 @@ function main({ len, duration, concurrent, encoding }) { const totalOps = reads + zips; benchEnded = true; bench.end(totalOps); - try { - fs.unlinkSync(filename); - } catch { - // Continue regardless of error. - } + + // This delay is needed because on windows this can cause + // race condition with afterRead, which makes this benchmark + // fails to delete the temp file + setTimeout(() => { + try { + fs.unlinkSync(filename); + } catch { + // Continue regardless of error. + } + }, 10); }, duration * 1000); function read() { diff --git a/benchmark/fs/readfile-permission-enabled.js b/benchmark/fs/readfile-permission-enabled.js index 6f762a402dfb5f..7e3d6e657dd9e9 100644 --- a/benchmark/fs/readfile-permission-enabled.js +++ b/benchmark/fs/readfile-permission-enabled.js @@ -41,12 +41,18 @@ function main({ len, duration, concurrent, encoding }) { setTimeout(() => { benchEnded = true; bench.end(reads); - try { - fs.unlinkSync(filename); - } catch { - // Continue regardless of error. - } - process.exit(0); + + // This delay is needed because on windows this can cause + // race condition with afterRead, which makes this benchmark + // fails to delete the temp file + setTimeout(() => { + try { + fs.unlinkSync(filename); + } catch { + // Continue regardless of error. + } + process.exit(0); + }, 10); }, duration * 1000); function read() { diff --git a/benchmark/fs/readfile-promises.js b/benchmark/fs/readfile-promises.js index b9fcab00333419..5139b92e884765 100644 --- a/benchmark/fs/readfile-promises.js +++ b/benchmark/fs/readfile-promises.js @@ -41,12 +41,18 @@ function main({ len, duration, concurrent, encoding }) { setTimeout(() => { benchEnded = true; bench.end(writes); - try { - fs.unlinkSync(filename); - } catch { - // Continue regardless of error. - } - process.exit(0); + + // This delay is needed because on windows this can cause + // race condition with afterRead, which makes this benchmark + // fails to delete the temp file + setTimeout(() => { + try { + fs.unlinkSync(filename); + } catch { + // Continue regardless of error. + } + process.exit(0); + }, 10); }, duration * 1000); function read() { diff --git a/benchmark/fs/readfile.js b/benchmark/fs/readfile.js index 24c2c5401ecf9c..ee16e083f55384 100644 --- a/benchmark/fs/readfile.js +++ b/benchmark/fs/readfile.js @@ -34,12 +34,18 @@ function main({ len, duration, concurrent, encoding }) { setTimeout(() => { benchEnded = true; bench.end(reads); - try { - fs.unlinkSync(filename); - } catch { - // Continue regardless of error. - } - process.exit(0); + + // This delay is needed because on windows this can cause + // race condition with afterRead, which makes this benchmark + // fails to delete the temp file + setTimeout(() => { + try { + fs.unlinkSync(filename); + } catch { + // Continue regardless of error. + } + process.exit(0); + }, 10); }, duration * 1000); function read() { diff --git a/benchmark/fs/writefile-promises.js b/benchmark/fs/writefile-promises.js index 2f3fd352aa886e..64ae3a4631ceaa 100644 --- a/benchmark/fs/writefile-promises.js +++ b/benchmark/fs/writefile-promises.js @@ -43,14 +43,20 @@ function main({ encodingType, duration, concurrent, size }) { setTimeout(() => { benchEnded = true; bench.end(writes); - for (let i = 0; i < filesWritten; i++) { - try { - fs.unlinkSync(`${filename}-${i}`); - } catch { - // Continue regardless of error. + + // This delay is needed because on windows this can cause + // race condition with afterRead, which makes this benchmark + // fails to delete the temp file + setTimeout(() => { + for (let i = 0; i < filesWritten; i++) { + try { + fs.unlinkSync(`${filename}-${i}`); + } catch { + // Continue regardless of error. + } } - } - process.exit(0); + process.exit(0); + }, 10); }, duration * 1000); function write() { From d900ac9ea8eb967650e0f1dd795e440ab34e7ae0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinicius=20Louren=C3=A7o?= <12551007+H4ad@users.noreply.github.com> Date: Sun, 8 Oct 2023 16:20:23 -0300 Subject: [PATCH 2/5] fixup! benchmark: fix race condition on fs benchs --- benchmark/fs/readfile-partitioned.js | 25 +++++----- benchmark/fs/readfile-permission-enabled.js | 44 ++++++++--------- benchmark/fs/readfile-promises.js | 52 ++++++++++----------- benchmark/fs/readfile.js | 49 +++++++++---------- benchmark/fs/writefile-promises.js | 41 +++++++++------- 5 files changed, 109 insertions(+), 102 deletions(-) diff --git a/benchmark/fs/readfile-partitioned.js b/benchmark/fs/readfile-partitioned.js index 2c3af9614c3d2f..5056ea8a6b0e6d 100644 --- a/benchmark/fs/readfile-partitioned.js +++ b/benchmark/fs/readfile-partitioned.js @@ -35,25 +35,26 @@ function main({ len, duration, concurrent, encoding }) { const zipData = Buffer.alloc(1024, 'a'); + let waitConcurrent = 0; let reads = 0; let zips = 0; let benchEnded = false; bench.start(); setTimeout(() => { - const totalOps = reads + zips; benchEnded = true; + + if (++waitConcurrent !== concurrent) { + return; + } + + const totalOps = reads + zips; bench.end(totalOps); - // This delay is needed because on windows this can cause - // race condition with afterRead, which makes this benchmark - // fails to delete the temp file - setTimeout(() => { - try { - fs.unlinkSync(filename); - } catch { - // Continue regardless of error. - } - }, 10); + try { + fs.unlinkSync(filename); + } catch { + // Continue regardless of error. + } }, duration * 1000); function read() { @@ -92,7 +93,7 @@ function main({ len, duration, concurrent, encoding }) { } // Start reads - while (concurrent-- > 0) read(); + for (let i = 0; i < concurrent; i++) read(); // Start a competing zip zip(); diff --git a/benchmark/fs/readfile-permission-enabled.js b/benchmark/fs/readfile-permission-enabled.js index 7e3d6e657dd9e9..5318661f0453aa 100644 --- a/benchmark/fs/readfile-permission-enabled.js +++ b/benchmark/fs/readfile-permission-enabled.js @@ -36,24 +36,24 @@ function main({ len, duration, concurrent, encoding }) { data = null; let reads = 0; - let benchEnded = false; + let waitConcurrent = 0; + + const startedAt = Date.now(); + const endAt = startedAt + (duration * 1000); + bench.start(); - setTimeout(() => { - benchEnded = true; + + function stop() { bench.end(reads); - // This delay is needed because on windows this can cause - // race condition with afterRead, which makes this benchmark - // fails to delete the temp file - setTimeout(() => { - try { - fs.unlinkSync(filename); - } catch { - // Continue regardless of error. - } - process.exit(0); - }, 10); - }, duration * 1000); + try { + fs.unlinkSync(filename); + } catch { + // Continue regardless of error. + } + + process.exit(0); + } function read() { fs.readFile(filename, encoding, afterRead); @@ -61,11 +61,6 @@ function main({ len, duration, concurrent, encoding }) { function afterRead(er, data) { if (er) { - if (er.code === 'ENOENT') { - // Only OK if unlinked by the timer from main. - assert.ok(benchEnded); - return; - } throw er; } @@ -73,9 +68,14 @@ function main({ len, duration, concurrent, encoding }) { throw new Error('wrong number of bytes returned'); reads++; - if (!benchEnded) + let benchEnded = Date.now() >= endAt; + + if (benchEnded && (++waitConcurrent) === concurrent) { + stop(); + } else if (!benchEnded) { read(); + } } - while (concurrent--) read(); + for (let i = 0; i < concurrent; i++) read(); } diff --git a/benchmark/fs/readfile-promises.js b/benchmark/fs/readfile-promises.js index 5139b92e884765..424932963e7502 100644 --- a/benchmark/fs/readfile-promises.js +++ b/benchmark/fs/readfile-promises.js @@ -35,25 +35,25 @@ function main({ len, duration, concurrent, encoding }) { fs.writeFileSync(filename, data); data = null; - let writes = 0; - let benchEnded = false; + let reads = 0; + let waitConcurrent = 0; + + const startedAt = Date.now(); + const endAt = startedAt + (duration * 1000); + bench.start(); - setTimeout(() => { - benchEnded = true; - bench.end(writes); - - // This delay is needed because on windows this can cause - // race condition with afterRead, which makes this benchmark - // fails to delete the temp file - setTimeout(() => { - try { - fs.unlinkSync(filename); - } catch { - // Continue regardless of error. - } - process.exit(0); - }, 10); - }, duration * 1000); + + function stop() { + bench.end(reads); + + try { + fs.unlinkSync(filename); + } catch { + // Continue regardless of error. + } + + process.exit(0); + } function read() { fs.promises.readFile(filename, encoding) @@ -63,21 +63,21 @@ function main({ len, duration, concurrent, encoding }) { function afterRead(er, data) { if (er) { - if (er.code === 'ENOENT') { - // Only OK if unlinked by the timer from main. - assert.ok(benchEnded); - return; - } throw er; } if (data.length !== len) throw new Error('wrong number of bytes returned'); - writes++; - if (!benchEnded) + reads++; + let benchEnded = Date.now() >= endAt; + + if (benchEnded && (++waitConcurrent) === concurrent) { + stop(); + } else if (!benchEnded) { read(); + } } - while (concurrent--) read(); + for (let i = 0; i < concurrent; i++) read(); } diff --git a/benchmark/fs/readfile.js b/benchmark/fs/readfile.js index ee16e083f55384..7e0bafa063633b 100644 --- a/benchmark/fs/readfile.js +++ b/benchmark/fs/readfile.js @@ -6,6 +6,7 @@ const common = require('../common.js'); const fs = require('fs'); const assert = require('assert'); +const { performance } = require('perf_hooks'); const tmpdir = require('../../test/common/tmpdir'); tmpdir.refresh(); @@ -29,36 +30,31 @@ function main({ len, duration, concurrent, encoding }) { data = null; let reads = 0; - let benchEnded = false; - bench.start(); - setTimeout(() => { - benchEnded = true; - bench.end(reads); + let waitConcurrent = 0; + + const startedAt = Date.now(); + const endAt = startedAt + (duration * 1000); - // This delay is needed because on windows this can cause - // race condition with afterRead, which makes this benchmark - // fails to delete the temp file - setTimeout(() => { - try { - fs.unlinkSync(filename); - } catch { - // Continue regardless of error. - } - process.exit(0); - }, 10); - }, duration * 1000); + bench.start(); function read() { fs.readFile(filename, encoding, afterRead); } + function stop() { + bench.end(reads); + + try { + fs.unlinkSync(filename); + } catch { + // Continue regardless of error. + } + + process.exit(0); + } + function afterRead(er, data) { if (er) { - if (er.code === 'ENOENT') { - // Only OK if unlinked by the timer from main. - assert.ok(benchEnded); - return; - } throw er; } @@ -66,9 +62,14 @@ function main({ len, duration, concurrent, encoding }) { throw new Error('wrong number of bytes returned'); reads++; - if (!benchEnded) + let benchEnded = Date.now() >= endAt; + + if (benchEnded && (++waitConcurrent) === concurrent) { + stop(); + } else if (!benchEnded) { read(); + } } - while (concurrent--) read(); + for (let i = 0; i < concurrent; i++) read(); } diff --git a/benchmark/fs/writefile-promises.js b/benchmark/fs/writefile-promises.js index 64ae3a4631ceaa..7687a51d06b6c7 100644 --- a/benchmark/fs/writefile-promises.js +++ b/benchmark/fs/writefile-promises.js @@ -38,26 +38,26 @@ function main({ encodingType, duration, concurrent, size }) { } let writes = 0; - let benchEnded = false; + let waitConcurrent = 0; + + const startedAt = Date.now(); + const endAt = startedAt + (duration * 1000); + bench.start(); - setTimeout(() => { - benchEnded = true; + + function stop() { bench.end(writes); - // This delay is needed because on windows this can cause - // race condition with afterRead, which makes this benchmark - // fails to delete the temp file - setTimeout(() => { - for (let i = 0; i < filesWritten; i++) { - try { - fs.unlinkSync(`${filename}-${i}`); - } catch { - // Continue regardless of error. - } + for (let i = 0; i < filesWritten; i++) { + try { + fs.unlinkSync(`${filename}-${i}`); + } catch { + // Continue regardless of error. } - process.exit(0); - }, 10); - }, duration * 1000); + } + + process.exit(0); + } function write() { fs.promises.writeFile(`${filename}-${filesWritten++}`, chunk, encoding) @@ -76,9 +76,14 @@ function main({ encodingType, duration, concurrent, size }) { } writes++; - if (!benchEnded) + let benchEnded = Date.now() >= endAt; + + if (benchEnded && (++waitConcurrent) === concurrent) { + stop(); + } else if (!benchEnded) { write(); + } } - while (concurrent--) write(); + for (let i = 0; i < concurrent; i++) write(); } From 625f575087f5948c4766891b22308234a1af555a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinicius=20Louren=C3=A7o?= <12551007+H4ad@users.noreply.github.com> Date: Sun, 8 Oct 2023 16:34:10 -0300 Subject: [PATCH 3/5] fixup! benchmark: fix race condition on fs benchs --- benchmark/fs/readfile-partitioned.js | 38 ++++++++++++++++------------ 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/benchmark/fs/readfile-partitioned.js b/benchmark/fs/readfile-partitioned.js index 5056ea8a6b0e6d..d0d6bdb9c0a1fe 100644 --- a/benchmark/fs/readfile-partitioned.js +++ b/benchmark/fs/readfile-partitioned.js @@ -36,17 +36,18 @@ function main({ len, duration, concurrent, encoding }) { const zipData = Buffer.alloc(1024, 'a'); let waitConcurrent = 0; + // plus one because of zip + let targetConcurrency = concurrent + 1; + + const startedAt = Date.now(); + const endAt = startedAt + (duration * 1000); + let reads = 0; let zips = 0; - let benchEnded = false; - bench.start(); - setTimeout(() => { - benchEnded = true; - - if (++waitConcurrent !== concurrent) { - return; - } + bench.start(); + + function stop() { const totalOps = reads + zips; bench.end(totalOps); @@ -55,7 +56,7 @@ function main({ len, duration, concurrent, encoding }) { } catch { // Continue regardless of error. } - }, duration * 1000); + } function read() { fs.readFile(filename, encoding, afterRead); @@ -63,11 +64,6 @@ function main({ len, duration, concurrent, encoding }) { function afterRead(er, data) { if (er) { - if (er.code === 'ENOENT') { - // Only OK if unlinked by the timer from main. - assert.ok(benchEnded); - return; - } throw er; } @@ -75,8 +71,13 @@ function main({ len, duration, concurrent, encoding }) { throw new Error('wrong number of bytes returned'); reads++; - if (!benchEnded) + let benchEnded = Date.now() >= endAt; + + if (benchEnded && (++waitConcurrent) === targetConcurrency) { + stop(); + } else if (!benchEnded) { read(); + } } function zip() { @@ -88,8 +89,13 @@ function main({ len, duration, concurrent, encoding }) { throw er; zips++; - if (!benchEnded) + let benchEnded = Date.now() >= endAt; + + if (benchEnded && (++waitConcurrent) === targetConcurrency) { + stop(); + } else if (!benchEnded) { zip(); + } } // Start reads From dad170243d13d3e3e64a422fcf576f9088bc4537 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinicius=20Louren=C3=A7o?= <12551007+H4ad@users.noreply.github.com> Date: Sun, 8 Oct 2023 16:35:00 -0300 Subject: [PATCH 4/5] fixup! benchmark: fix race condition on fs benchs --- benchmark/fs/readfile-partitioned.js | 1 - 1 file changed, 1 deletion(-) diff --git a/benchmark/fs/readfile-partitioned.js b/benchmark/fs/readfile-partitioned.js index d0d6bdb9c0a1fe..103932af25fa4f 100644 --- a/benchmark/fs/readfile-partitioned.js +++ b/benchmark/fs/readfile-partitioned.js @@ -14,7 +14,6 @@ const filename = path.resolve(__dirname, `.removeme-benchmark-garbage-${process.pid}`); const fs = require('fs'); const zlib = require('zlib'); -const assert = require('assert'); const bench = common.createBenchmark(main, { duration: [5], From 07d29e0d6958189e4892215e5b9c1165a249d256 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vinicius=20Louren=C3=A7o?= <12551007+H4ad@users.noreply.github.com> Date: Sun, 8 Oct 2023 16:42:25 -0300 Subject: [PATCH 5/5] fixup! benchmark: fix race condition on fs benchs --- benchmark/fs/readfile-partitioned.js | 10 +++++----- benchmark/fs/readfile-permission-enabled.js | 5 ++--- benchmark/fs/readfile-promises.js | 3 +-- benchmark/fs/readfile.js | 4 +--- benchmark/fs/writefile-promises.js | 10 ++-------- 5 files changed, 11 insertions(+), 21 deletions(-) diff --git a/benchmark/fs/readfile-partitioned.js b/benchmark/fs/readfile-partitioned.js index 103932af25fa4f..5a2004873e9fa0 100644 --- a/benchmark/fs/readfile-partitioned.js +++ b/benchmark/fs/readfile-partitioned.js @@ -35,9 +35,9 @@ function main({ len, duration, concurrent, encoding }) { const zipData = Buffer.alloc(1024, 'a'); let waitConcurrent = 0; - // plus one because of zip - let targetConcurrency = concurrent + 1; + // Plus one because of zip + const targetConcurrency = concurrent + 1; const startedAt = Date.now(); const endAt = startedAt + (duration * 1000); @@ -45,7 +45,7 @@ function main({ len, duration, concurrent, encoding }) { let zips = 0; bench.start(); - + function stop() { const totalOps = reads + zips; bench.end(totalOps); @@ -70,7 +70,7 @@ function main({ len, duration, concurrent, encoding }) { throw new Error('wrong number of bytes returned'); reads++; - let benchEnded = Date.now() >= endAt; + const benchEnded = Date.now() >= endAt; if (benchEnded && (++waitConcurrent) === targetConcurrency) { stop(); @@ -88,7 +88,7 @@ function main({ len, duration, concurrent, encoding }) { throw er; zips++; - let benchEnded = Date.now() >= endAt; + const benchEnded = Date.now() >= endAt; if (benchEnded && (++waitConcurrent) === targetConcurrency) { stop(); diff --git a/benchmark/fs/readfile-permission-enabled.js b/benchmark/fs/readfile-permission-enabled.js index 5318661f0453aa..46f20be6a0b06e 100644 --- a/benchmark/fs/readfile-permission-enabled.js +++ b/benchmark/fs/readfile-permission-enabled.js @@ -5,7 +5,6 @@ const common = require('../common.js'); const fs = require('fs'); -const assert = require('assert'); const tmpdir = require('../../test/common/tmpdir'); tmpdir.refresh(); @@ -42,7 +41,7 @@ function main({ len, duration, concurrent, encoding }) { const endAt = startedAt + (duration * 1000); bench.start(); - + function stop() { bench.end(reads); @@ -68,7 +67,7 @@ function main({ len, duration, concurrent, encoding }) { throw new Error('wrong number of bytes returned'); reads++; - let benchEnded = Date.now() >= endAt; + const benchEnded = Date.now() >= endAt; if (benchEnded && (++waitConcurrent) === concurrent) { stop(); diff --git a/benchmark/fs/readfile-promises.js b/benchmark/fs/readfile-promises.js index 424932963e7502..f1df92931b35a0 100644 --- a/benchmark/fs/readfile-promises.js +++ b/benchmark/fs/readfile-promises.js @@ -5,7 +5,6 @@ const common = require('../common.js'); const fs = require('fs'); -const assert = require('assert'); const tmpdir = require('../../test/common/tmpdir'); tmpdir.refresh(); @@ -70,7 +69,7 @@ function main({ len, duration, concurrent, encoding }) { throw new Error('wrong number of bytes returned'); reads++; - let benchEnded = Date.now() >= endAt; + const benchEnded = Date.now() >= endAt; if (benchEnded && (++waitConcurrent) === concurrent) { stop(); diff --git a/benchmark/fs/readfile.js b/benchmark/fs/readfile.js index 7e0bafa063633b..9f74508042205f 100644 --- a/benchmark/fs/readfile.js +++ b/benchmark/fs/readfile.js @@ -5,8 +5,6 @@ const common = require('../common.js'); const fs = require('fs'); -const assert = require('assert'); -const { performance } = require('perf_hooks'); const tmpdir = require('../../test/common/tmpdir'); tmpdir.refresh(); @@ -62,7 +60,7 @@ function main({ len, duration, concurrent, encoding }) { throw new Error('wrong number of bytes returned'); reads++; - let benchEnded = Date.now() >= endAt; + const benchEnded = Date.now() >= endAt; if (benchEnded && (++waitConcurrent) === concurrent) { stop(); diff --git a/benchmark/fs/writefile-promises.js b/benchmark/fs/writefile-promises.js index 7687a51d06b6c7..41c029051bc04d 100644 --- a/benchmark/fs/writefile-promises.js +++ b/benchmark/fs/writefile-promises.js @@ -5,7 +5,6 @@ const common = require('../common.js'); const fs = require('fs'); -const assert = require('assert'); const tmpdir = require('../../test/common/tmpdir'); tmpdir.refresh(); @@ -44,7 +43,7 @@ function main({ encodingType, duration, concurrent, size }) { const endAt = startedAt + (duration * 1000); bench.start(); - + function stop() { bench.end(writes); @@ -67,16 +66,11 @@ function main({ encodingType, duration, concurrent, size }) { function afterWrite(er) { if (er) { - if (er.code === 'ENOENT') { - // Only OK if unlinked by the timer from main. - assert.ok(benchEnded); - return; - } throw er; } writes++; - let benchEnded = Date.now() >= endAt; + const benchEnded = Date.now() >= endAt; if (benchEnded && (++waitConcurrent) === concurrent) { stop();