1// Test the throughput of the fs.WriteStream class.
2'use strict';
3
4const path = require('path');
5const common = require('../common.js');
6const fs = require('fs');
7const assert = require('assert');
8
9const tmpdir = require('../../test/common/tmpdir');
10tmpdir.refresh();
11const filename = path.resolve(tmpdir.path,
12                              `.removeme-benchmark-garbage-${process.pid}`);
13
14const bench = common.createBenchmark(main, {
15  encodingType: ['buf', 'asc', 'utf'],
16  filesize: [1000 * 1024],
17  highWaterMark: [1024, 4096, 65535, 1024 * 1024],
18  n: 1024,
19});
20
21function main(conf) {
22  const { encodingType, highWaterMark, filesize } = conf;
23  let { n } = conf;
24
25  let encoding = '';
26  switch (encodingType) {
27    case 'buf':
28      encoding = null;
29      break;
30    case 'asc':
31      encoding = 'ascii';
32      break;
33    case 'utf':
34      encoding = 'utf8';
35      break;
36    default:
37      throw new Error(`invalid encodingType: ${encodingType}`);
38  }
39
40  // Make file
41  const buf = Buffer.allocUnsafe(filesize);
42  if (encoding === 'utf8') {
43    // ü
44    for (let i = 0; i < buf.length; i++) {
45      buf[i] = i % 2 === 0 ? 0xC3 : 0xBC;
46    }
47  } else if (encoding === 'ascii') {
48    buf.fill('a');
49  } else {
50    buf.fill('x');
51  }
52
53  try {
54    fs.unlinkSync(filename);
55  } catch {
56    // Continue regardless of error.
57  }
58  const ws = fs.createWriteStream(filename);
59  ws.on('close', runTest.bind(null, filesize, highWaterMark, encoding, n));
60  ws.on('drain', write);
61  write();
62  function write() {
63    do {
64      n--;
65    } while (false !== ws.write(buf) && n > 0);
66    if (n === 0)
67      ws.end();
68  }
69}
70
71function runTest(filesize, highWaterMark, encoding, n) {
72  assert(fs.statSync(filename).size === filesize * n);
73  const rs = fs.createReadStream(filename, {
74    highWaterMark,
75    encoding,
76  });
77
78  rs.on('open', () => {
79    bench.start();
80  });
81
82  let bytes = 0;
83  rs.on('data', (chunk) => {
84    bytes += chunk.length;
85  });
86
87  rs.on('end', () => {
88    try {
89      fs.unlinkSync(filename);
90    } catch {
91      // Continue regardless of error.
92    }
93    // MB/sec
94    bench.end(bytes / (1024 * 1024));
95  });
96}
97