Skip to content

fs: Optimizations 3: The Revenge #12105

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Closed
wants to merge 15 commits into from
Closed
17 changes: 17 additions & 0 deletions benchmark/fs/read-stream-create.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use strict';

const common = require('../common.js');
const createReadStream = require('fs').createReadStream;

const bench = common.createBenchmark(main, {
n: [2e6]
});

function main(conf) {
var n = +conf.n;

bench.start();
for (var i = 0; i < n; ++i)
createReadStream(null, { fd: 0 });
bench.end(n);
}
49 changes: 49 additions & 0 deletions benchmark/fs/read-stream-throughput-dur.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use strict';

if (process.platform === 'win32')
throw new Error('This benchmark is not compatible with Windows');

const common = require('../common.js');
const fs = require('fs');

const bench = common.createBenchmark(main, {
type: ['buf', 'asc', 'utf'],
dur: [5],
size: [1024, 4096, 65535, 1024 * 1024]
});

function main(conf) {
const dur = +conf.dur * 1000;
const hwm = +conf.size;
var bytes = 0;
var encoding;

switch (conf.type) {
case 'buf':
encoding = null;
break;
case 'asc':
encoding = 'ascii';
break;
case 'utf':
encoding = 'utf8';
break;
default:
throw new Error('invalid type');
}

setTimeout(() => {
// MB/sec
bench.end(bytes / (1024 * 1024));
process.exit(0);
}, dur);

fs.createReadStream('/dev/zero', {
highWaterMark: hwm,
encoding: encoding
}).on('open', function() {
bench.start();
}).on('data', function(chunk) {
bytes += chunk.length;
});
}
23 changes: 12 additions & 11 deletions benchmark/fs/read-stream-throughput.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
// test the throughput of the fs.WriteStream class.
'use strict';

var path = require('path');
var common = require('../common.js');
var filename = path.resolve(__dirname, '.removeme-benchmark-garbage');
var fs = require('fs');
var filesize = 1000 * 1024 * 1024;
var assert = require('assert');
const path = require('path');
const common = require('../common.js');
const filename = path.resolve(__dirname, '.removeme-benchmark-garbage');
const fs = require('fs');
const filesize = 1000 * 1024 * 1024;
const assert = require('assert');

var type, encoding, size;
var type;
var encoding;
var size;

var bench = common.createBenchmark(main, {
const bench = common.createBenchmark(main, {
type: ['buf', 'asc', 'utf'],
size: [1024, 4096, 65535, 1024 * 1024]
});
Expand Down Expand Up @@ -53,9 +54,9 @@ function runTest() {
});

rs.on('end', function() {
try { fs.unlinkSync(filename); } catch (e) {}
// MB/sec
bench.end(bytes / (1024 * 1024));
try { fs.unlinkSync(filename); } catch (e) {}
});
}

Expand All @@ -81,7 +82,7 @@ function makeFile() {
function write() {
do {
w--;
} while (false !== ws.write(buf) && w > 0);
} while (ws.write(buf) !== false && w > 0);
if (w === 0)
ws.end();
}
Expand Down
32 changes: 13 additions & 19 deletions benchmark/fs/readfile.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,31 @@
// Call fs.readFile over and over again really fast.
// Then see how many times it got called.
// Yes, this is a silly benchmark. Most benchmarks are silly.
'use strict';

var path = require('path');
var common = require('../common.js');
var filename = path.resolve(__dirname, '.removeme-benchmark-garbage');
var fs = require('fs');
const path = require('path');
const common = require('../common.js');
const filename = path.resolve(__dirname, '.removeme-benchmark-garbage');
const fs = require('fs');

var bench = common.createBenchmark(main, {
const bench = common.createBenchmark(main, {
dur: [5],
len: [1024, 16 * 1024 * 1024],
concurrent: [1, 10]
});

function main(conf) {
var len = +conf.len;
const len = +conf.len;
const dur = +conf.dur * 1000;
var cur = +conf.concurrent;
var reads = 0;

try { fs.unlinkSync(filename); } catch (e) {}
var data = Buffer.alloc(len, 'x');
fs.writeFileSync(filename, data);
data = null;
fs.writeFileSync(filename, Buffer.alloc(len, 'x'));

var reads = 0;
var bench_ended = false;
bench.start();
setTimeout(function() {
bench_ended = true;
bench.end(reads);
try { fs.unlinkSync(filename); } catch (e) {}
process.exit(0);
}, +conf.dur * 1000);
}, dur);

function read() {
fs.readFile(filename, afterRead);
Expand All @@ -43,10 +39,8 @@ function main(conf) {
throw new Error('wrong number of bytes returned');

reads++;
if (!bench_ended)
read();
read();
}

var cur = +conf.concurrent;
while (cur--) read();
}
37 changes: 21 additions & 16 deletions benchmark/fs/write-stream-throughput.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
// test the throughput of the fs.WriteStream class.
'use strict';

var path = require('path');
var common = require('../common.js');
var filename = path.resolve(__dirname, '.removeme-benchmark-garbage');
var fs = require('fs');
const path = require('path');
const common = require('../common.js');
const filename = path.resolve(__dirname, '.removeme-benchmark-garbage');
const fs = require('fs');

var bench = common.createBenchmark(main, {
const bench = common.createBenchmark(main, {
dur: [5],
file: [''],
type: ['buf', 'asc', 'utf'],
size: [2, 1024, 65535, 1024 * 1024]
});

function main(conf) {
var dur = +conf.dur;
var type = conf.type;
var size = +conf.size;
const dur = +conf.dur * 1000;
const type = conf.type;
const size = +conf.size;
const file = (conf.file.length === 0 ? filename : conf.file);
var encoding;

var chunk;
Expand All @@ -35,27 +36,31 @@ function main(conf) {
throw new Error('invalid type');
}

try { fs.unlinkSync(filename); } catch (e) {}
try { fs.unlinkSync(file); } catch (e) {}

var started = false;
var ending = false;
var ended = false;
var written = 0;

setTimeout(function() {
ending = true;
f.end();
}, dur * 1000);
}, dur);

var f = fs.createWriteStream(filename);
var f = fs.createWriteStream(file);
f.on('drain', write);
f.on('open', write);
f.on('close', done);
f.on('finish', function() {
ended = true;
var written = fs.statSync(filename).size / 1024;
try { fs.unlinkSync(filename); } catch (e) {}
bench.end(written / 1024);
ended = true;
try { fs.unlinkSync(file); } catch (e) {}
});

function wroteChunk() {
written += size;
}

function write() {
// don't try to write after we end, even if a 'drain' event comes.
Expand All @@ -68,7 +73,7 @@ function main(conf) {
bench.start();
}

while (false !== f.write(chunk, encoding));
while (f.write(chunk, encoding, wroteChunk) !== false);
}

function done() {
Expand Down
75 changes: 75 additions & 0 deletions benchmark/fs/writeFile.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
'use strict';

const path = require('path');
const common = require('../common.js');
const filename = path.resolve(__dirname, '.removeme-benchmark-garbage');
const fs = require('fs');
const writeFile = fs.writeFile;

const bench = common.createBenchmark(main, {
dur: [5],
file: [''],
type: ['buf', 'asc', 'utf'],
size: [2, 1024, 64 * 1024, 1024 * 1024]
});

function main(conf) {
const dur = +conf.dur * 1000;
const size = +conf.size;
const file = (conf.file.length === 0 ? filename : conf.file);
var writes = 0;
var ended = false;
var encoding;
var data;

try { fs.unlinkSync(file); } catch (e) {}
process.on('exit', function() {
try { fs.unlinkSync(file); } catch (e) {}
});

setTimeout(function() {
bench.end(writes);
ended = true;
}, dur);

switch (conf.type) {
case 'buf':
data = Buffer.alloc(size, 'b');
(function() {
function afterWrite(err) {
if (err)
throw err;
if (ended)
return;
++writes;
writeFile(file, data, afterWrite);
}
bench.start();
writeFile(file, data, afterWrite);
})();
return;
case 'asc':
data = new Array(size + 1).join('a');
encoding = 'ascii';
break;
case 'utf':
data = new Array(Math.ceil(size / 2) + 1).join('ü');
encoding = 'utf8';
break;
default:
throw new Error('invalid type');
}

(function() {
function afterWrite(err) {
if (err)
throw err;
if (ended)
return;
++writes;
writeFile(file, data, encoding, afterWrite);
}
bench.start();
writeFile(file, data, encoding, afterWrite);
})();
}
53 changes: 53 additions & 0 deletions benchmark/fs/writeFileSync.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use strict';

const path = require('path');
const common = require('../common.js');
const filename = path.resolve(__dirname, '.removeme-benchmark-garbage');
const fs = require('fs');
const writeFileSync = fs.writeFileSync;

const bench = common.createBenchmark(main, {
n: [1e5],
file: [''],
type: ['buf', 'asc', 'utf'],
size: [2, 1024, 64 * 1024, 1024 * 1024]
});

function main(conf) {
const n = +conf.n;
const size = +conf.size;
const file = (conf.file.length === 0 ? filename : conf.file);
var encoding;
var data;
var i;

try { fs.unlinkSync(file); } catch (e) {}
process.on('exit', function() {
try { fs.unlinkSync(file); } catch (e) {}
});

switch (conf.type) {
case 'buf':
data = Buffer.alloc(size, 'b');
bench.start();
for (i = 0; i < n; ++i)
writeFileSync(file, data);
bench.end(n);
return;
case 'asc':
data = new Array(size + 1).join('a');
encoding = 'ascii';
break;
case 'utf':
data = new Array(Math.ceil(size / 2) + 1).join('ü');
encoding = 'utf8';
break;
default:
throw new Error('invalid type');
}

bench.start();
for (i = 0; i < n; ++i)
writeFileSync(file, data, encoding);
bench.end(n);
}
Loading