Skip to content

Commit

Permalink
Allow configuring the number of threads (#173)
Browse files Browse the repository at this point in the history
  • Loading branch information
XhmikosR authored Feb 9, 2022
1 parent e2c896d commit e6993a4
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 8 deletions.
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ When combined with a watching task (such as [grunt-contrib-watch][watch]), even

## Options

### `threads`

* Type: `String`, `Boolean`, `Number`
* Default: `auto`, which is the number of threads -1

Use this option to control the number of threads that grunt-htmllint will use when validating a big number of files. This will spawn as many Java processes as the number of threads.

### `ignore`

* Type: `Array`, `String`, or `RegExp`
Expand Down
31 changes: 31 additions & 0 deletions lib/getThreads.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use strict';

const os = require('os');

// eslint-disable-next-line unicorn/explicit-length-check
const CPUS = os.cpus() && os.cpus().length;
const THREADS = CPUS > 2 ? CPUS - 1 : 1;

function getThreads(config) {
const { threads } = config;

switch (threads) {
case 'auto':
case -1:
case '':
case true:
case null:
case undefined:
return THREADS;
case 0:
case 1:
case false:
return 1;
default:
if (threads > 1) {
return threads;
}
}
}

module.exports = getThreads;
11 changes: 4 additions & 7 deletions lib/htmllint.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
'use strict';

const os = require('os');
const path = require('path');
const { execFile } = require('child_process');
const async = require('async');
const chunkify = require('./chunkify.js');
const javaDetect = require('./javaDetect.js');
const getThreads = require('./getThreads.js');
const javaArgs = require('./javaArgs.js');
const javaDetect = require('./javaDetect.js');
const parseErrorMessages = require('./parseErrorMessages.js');
const processErrorMessages = require('./processErrorMessages.js');

Expand All @@ -20,10 +20,6 @@ const MAX_CHARS = 5000;
*/
const MAX_BUFFER = 20_000 * 1024;

// eslint-disable-next-line unicorn/explicit-length-check
const CPUS = os.cpus() && os.cpus().length;
const THREADS = CPUS > 2 ? CPUS - 1 : 1;

function htmllint(config, done) {
if (config.files.length === 0) {
return done(null, []);
Expand All @@ -42,8 +38,9 @@ function htmllint(config, done) {

const files = config.files.map(file => path.normalize(file));
const chunks = chunkify(files, MAX_CHARS);
const threads = getThreads(config);

async.mapLimit(chunks, THREADS, (chunk, cb) => {
async.mapLimit(chunks, threads, (chunk, cb) => {
const args = javaArgs(java, chunk, config);

execFile('java', args, { maxBuffer: MAX_BUFFER, shell: true }, (error, stdout, stderr) => {
Expand Down
3 changes: 2 additions & 1 deletion tasks/html.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ module.exports = grunt => {
force: false,
absoluteFilePathsForReporter: false,
errorlevels: ['info', 'warning', 'error'],
noLangDetect: false
noLangDetect: false,
threads: 'auto'
});
const { force } = options;
let { reporterOutput } = options;
Expand Down
49 changes: 49 additions & 0 deletions test/threads_test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use strict';

const assert = require('assert').strict;
const os = require('os');
const getThreads = require('../lib/getThreads.js');

// eslint-disable-next-line unicorn/explicit-length-check
const CPUS = os.cpus() && os.cpus().length;
const THREADS = CPUS > 2 ? CPUS - 1 : 1;

describe('getThreads', () => {
it('should use the number of available threads -1', done => {
const config = {};

for (const option of ['auto', -1, '', true, null, undefined]) {
config.threads = option;
const expected = THREADS;
const actual = getThreads(config);

assert.equal(actual, expected, `"thread: ${option}" failed!`);
}

done();
});

it('should return 1 with false, 0, or 1', done => {
const config = {};

for (const option of [0, 1, false]) {
config.threads = option;
const expected = 1;
const actual = getThreads(config);
assert.equal(actual, expected);
}

done();
});

it('should return the number of threads', done => {
const config = {
threads: 4
};
const expected = 4;
const actual = getThreads(config);

assert.equal(actual, expected);
done();
});
});

0 comments on commit e6993a4

Please sign in to comment.