Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Bugfix and performance improvements #3

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions benchmark/benchmark.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
const Benchmark = require('benchmark')
const nativeFn = require('./native.cjs')
const syncThreadsFn = require('./sync-threads.cjs')
const synckitFn = require('./synckit.cjs')

let previousMemory = 0;

function memoryUsage(name) {
const currentMemory = process.memoryUsage().rss
const diff = currentMemory-previousMemory
const sign = diff > 0 ? '+' : '';

console.log(`[${name}] Memory usage ${currentMemory/1000000}MB (${sign}${diff/1000000}MB)`);

previousMemory = currentMemory;
}

memoryUsage('initial')

function runAndPrint(suite) {
// add listeners
suite
.on('cycle', function (event) {
memoryUsage(`after ${event.target.name}`)
})
.on('complete', function () {
console.log()
const fastest = this.filter('fastest').map('name')
console.log('Fastest is ' + fastest)

var bySpeed = this.filter('successful').sort(function (a, b) {
a = a.stats
b = b.stats
return a.mean + a.moe > b.mean + b.moe ? -1 : 1
})

const results = []
let result
while ((result = bySpeed.pop())) {
//console.log(result)
results.push({
'Task Name': result.name,
'ops/sec': result.hz.toLocaleString('en-US', {
maximumFractionDigits: 0,
}),
//'Average Time (ns)': result.stats.mean * 1e9,
Margin: `\xB1 ${result.stats.rme.toFixed(2)}%`,
Samples: result.stats.sample.length,
})
}

console.table(results)
})
.run()
}

console.log('Load time')
const loadBench = new Benchmark.Suite()
loadBench
.add('native', () => {
return require('./native.cjs')
})
.add('sync-threads', () => {
return require('./sync-threads.cjs')
})
.add('synckit', () => {
return require('./synckit.cjs')
})

runAndPrint(loadBench)

console.log('Execution time')
const hotBench = new Benchmark.Suite()
hotBench
.add('native', () => {
return nativeFn(__filename)
})
.add('sync-threads', () => {
return syncThreadsFn(__filename)
})
.add('synckit', () => {
return synckitFn(__filename)
})

runAndPrint(hotBench)

console.log('Total time')
const totalBench = new Benchmark.Suite()
totalBench
.add('native', () => {
const fn = require('./native.cjs')
return fn(__filename)
})
.add('sync-threads', () => {
const fn = require('./sync-threads.cjs')
return fn(__filename)
})
.add('synckit', () => {
const fn = require('./synckit.cjs')
return fn(__filename)
})

runAndPrint(totalBench)
3 changes: 3 additions & 0 deletions benchmark/native.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
const fs = require('node:fs')

module.exports = filename => fs.readFileSync(filename, 'utf8')
8 changes: 8 additions & 0 deletions benchmark/sync-threads.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const { createSyncFn } = require('../src/index.js')

/**
* @type {() => string}
*/
const syncFn = createSyncFn(require.resolve('./sync-threads.worker.cjs'))

module.exports = syncFn
5 changes: 5 additions & 0 deletions benchmark/sync-threads.worker.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const fs = require('node:fs')

const { runAsWorker } = require('../src/index.js')

runAsWorker((filename) => fs.promises.readFile(filename, 'utf8'))
10 changes: 10 additions & 0 deletions benchmark/synckit.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Using 'synckit' here could skew the benchmark as it would need
// to apply module resolution that isn't needed for sync-threads.
const { createSyncFn } = require('../node_modules/synckit/lib/index.cjs')

/**
* @type {() => string}
*/
const syncFn = createSyncFn(require.resolve('./synckit.worker.cjs'))

module.exports = syncFn
7 changes: 7 additions & 0 deletions benchmark/synckit.worker.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
const fs = require('node:fs')

// Using 'synckit' here could skew the benchmark as it would need
// to apply module resolution that isn't needed for sync-threads.
const { runAsWorker } = require('../node_modules/synckit/lib/index.cjs')

runAsWorker((filename) => fs.promises.readFile(filename, 'utf8'))
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@
],
"devDependencies": {
"@types/node": "^12.19.3",
"benchmark": "^2.1.4",
"eslint": "^7.12.1",
"eslint-config-prettier": "^6.15.0",
"prettier": "^2.1.2",
"synckit": "^0.8.8",
"typescript": "^4.0.5"
},
"scripts": {
"declaration": "tsc -p declaration.tsconfig.json",
"build": "npm run declaration",
"prepare": "npm run build",
"lint": "prettier -c . && eslint ."
"lint": "prettier -c . && eslint .",
"test": "node --test test/index.test.js"
},
"prettier": {
"semi": false,
Expand Down
33 changes: 33 additions & 0 deletions src/SharedArrayBuffer.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Adds definitions missing from TypeScript, this feature is available since Node.js 20

interface SharedArrayBufferOptions {
maxByteLength?: number
}

interface SharedArrayBufferConstructor {
readonly prototype: SharedArrayBuffer
new (
byteLength: number,
options?: SharedArrayBufferOptions,
): SharedArrayBuffer
}

/**
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer/grow#specifications
*/
interface SharedArrayBuffer {
/**
* returns whether this SharedArrayBuffer can be grow or not.
*/
readonly growable?: boolean

/**
* returns the maximum length (in bytes) that this SharedArrayBuffer can be grown to.
*/
readonly maxByteLength?: number

/**
* grows the SharedArrayBuffer to the specified size, in bytes.
*/
grow?(newLength: number): void
}
Loading