From 34f476935e756828568e7f6e2cbee4341551e7a4 Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Fri, 1 Mar 2024 15:48:11 -0300 Subject: [PATCH 01/12] doc: add initial README --- README.md | 19 +++++++++++++++++++ pnpm-lock.yaml | 8 ++++---- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3bf4f3d..f6c7876 100644 --- a/README.md +++ b/README.md @@ -1 +1,20 @@ # nodejs-package-benchmark + +This package allows you to benchmark different runtimes using popular +packages operations. + +## Supported packages + +- [x] fastify +- [x] lodash +- [ ] prettier +- [ ] webpack +- [ ] babel +- [ ] moment +- [ ] dotenv +- [ ] pinojs +- [ ] winston +- [ ] helmet +- [ ] node-sass +- [ ] underscore +- [ ] minify diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 12d5c35..2509af2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,9 +1,5 @@ lockfileVersion: '6.0' -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - dependencies: fastify: specifier: 4.26.1 @@ -700,3 +696,7 @@ packages: /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false From 8431256c0bae5e38d55ed119d2312e0356c87add Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Fri, 1 Mar 2024 16:46:46 -0300 Subject: [PATCH 02/12] src: temporary disable fastify HTTP benchmarks are non-deterministc and until we adapt this framework to perform more than one benchmark for each type: 'http' I would not consider its results as valid or reliable. --- src/{fastify-benchmark.js => fastify-benchmark-disabled.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{fastify-benchmark.js => fastify-benchmark-disabled.js} (100%) diff --git a/src/fastify-benchmark.js b/src/fastify-benchmark-disabled.js similarity index 100% rename from src/fastify-benchmark.js rename to src/fastify-benchmark-disabled.js From 8294a413cbad55a23c8d118427adc946c444b268 Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Fri, 1 Mar 2024 21:03:02 -0300 Subject: [PATCH 03/12] feat: add prettier benchmark --- README.md | 2 +- fixtures/lodash.fp.js | 1031 +++++++++++++++++++++++++++++++++++++ index.js | 3 +- package.json | 3 +- pnpm-lock.yaml | 17 +- src/prettier-benchmark.js | 51 ++ 6 files changed, 1099 insertions(+), 8 deletions(-) create mode 100644 fixtures/lodash.fp.js create mode 100644 src/prettier-benchmark.js diff --git a/README.md b/README.md index f6c7876..bd261f0 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ packages operations. - [x] fastify - [x] lodash -- [ ] prettier +- [x] prettier - [ ] webpack - [ ] babel - [ ] moment diff --git a/fixtures/lodash.fp.js b/fixtures/lodash.fp.js new file mode 100644 index 0000000..a915b4c --- /dev/null +++ b/fixtures/lodash.fp.js @@ -0,0 +1,1031 @@ +(function webpackUniversalModuleDefinition(root, factory) { + if(typeof exports === 'object' && typeof module === 'object') + module.exports = factory(); + else if(typeof define === 'function' && define.amd) + define([], factory); + else if(typeof exports === 'object') + exports["fp"] = factory(); + else + root["fp"] = factory(); +})(this, function() { +return /******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; + +/******/ // The require function +/******/ function __webpack_require__(moduleId) { + +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) +/******/ return installedModules[moduleId].exports; + +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ exports: {}, +/******/ id: moduleId, +/******/ loaded: false +/******/ }; + +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); + +/******/ // Flag the module as loaded +/******/ module.loaded = true; + +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } + + +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; + +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; + +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; + +/******/ // Load entry module and return exports +/******/ return __webpack_require__(0); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + + var baseConvert = __webpack_require__(1); + + /** + * Converts `lodash` to an immutable auto-curried iteratee-first data-last + * version with conversion `options` applied. + * + * @param {Function} lodash The lodash function to convert. + * @param {Object} [options] The options object. See `baseConvert` for more details. + * @returns {Function} Returns the converted `lodash`. + */ + function browserConvert(lodash, options) { + return baseConvert(lodash, lodash, options); + } + + if (typeof _ == 'function' && typeof _.runInContext == 'function') { + _ = browserConvert(_.runInContext()); + } + module.exports = browserConvert; + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + + var mapping = __webpack_require__(2), + fallbackHolder = __webpack_require__(3); + + /** Built-in value reference. */ + var push = Array.prototype.push; + + /** + * Creates a function, with an arity of `n`, that invokes `func` with the + * arguments it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {number} n The arity of the new function. + * @returns {Function} Returns the new function. + */ + function baseArity(func, n) { + return n == 2 + ? function(a, b) { return func.apply(undefined, arguments); } + : function(a) { return func.apply(undefined, arguments); }; + } + + /** + * Creates a function that invokes `func`, with up to `n` arguments, ignoring + * any additional arguments. + * + * @private + * @param {Function} func The function to cap arguments for. + * @param {number} n The arity cap. + * @returns {Function} Returns the new function. + */ + function baseAry(func, n) { + return n == 2 + ? function(a, b) { return func(a, b); } + : function(a) { return func(a); }; + } + + /** + * Creates a clone of `array`. + * + * @private + * @param {Array} array The array to clone. + * @returns {Array} Returns the cloned array. + */ + function cloneArray(array) { + var length = array ? array.length : 0, + result = Array(length); + + while (length--) { + result[length] = array[length]; + } + return result; + } + + /** + * Creates a function that clones a given object using the assignment `func`. + * + * @private + * @param {Function} func The assignment function. + * @returns {Function} Returns the new cloner function. + */ + function createCloner(func) { + return function(object) { + return func({}, object); + }; + } + + /** + * A specialized version of `_.spread` which flattens the spread array into + * the arguments of the invoked `func`. + * + * @private + * @param {Function} func The function to spread arguments over. + * @param {number} start The start position of the spread. + * @returns {Function} Returns the new function. + */ + function flatSpread(func, start) { + return function() { + var length = arguments.length, + lastIndex = length - 1, + args = Array(length); + + while (length--) { + args[length] = arguments[length]; + } + var array = args[start], + otherArgs = args.slice(0, start); + + if (array) { + push.apply(otherArgs, array); + } + if (start != lastIndex) { + push.apply(otherArgs, args.slice(start + 1)); + } + return func.apply(this, otherArgs); + }; + } + + /** + * Creates a function that wraps `func` and uses `cloner` to clone the first + * argument it receives. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} cloner The function to clone arguments. + * @returns {Function} Returns the new immutable function. + */ + function wrapImmutable(func, cloner) { + return function() { + var length = arguments.length; + if (!length) { + return; + } + var args = Array(length); + while (length--) { + args[length] = arguments[length]; + } + var result = args[0] = cloner.apply(undefined, args); + func.apply(undefined, args); + return result; + }; + } + + /** + * The base implementation of `convert` which accepts a `util` object of methods + * required to perform conversions. + * + * @param {Object} util The util object. + * @param {string} name The name of the function to convert. + * @param {Function} func The function to convert. + * @param {Object} [options] The options object. + * @param {boolean} [options.cap=true] Specify capping iteratee arguments. + * @param {boolean} [options.curry=true] Specify currying. + * @param {boolean} [options.fixed=true] Specify fixed arity. + * @param {boolean} [options.immutable=true] Specify immutable operations. + * @param {boolean} [options.rearg=true] Specify rearranging arguments. + * @returns {Function|Object} Returns the converted function or object. + */ + function baseConvert(util, name, func, options) { + var isLib = typeof name == 'function', + isObj = name === Object(name); + + if (isObj) { + options = func; + func = name; + name = undefined; + } + if (func == null) { + throw new TypeError; + } + options || (options = {}); + + var config = { + 'cap': 'cap' in options ? options.cap : true, + 'curry': 'curry' in options ? options.curry : true, + 'fixed': 'fixed' in options ? options.fixed : true, + 'immutable': 'immutable' in options ? options.immutable : true, + 'rearg': 'rearg' in options ? options.rearg : true + }; + + var defaultHolder = isLib ? func : fallbackHolder, + forceCurry = ('curry' in options) && options.curry, + forceFixed = ('fixed' in options) && options.fixed, + forceRearg = ('rearg' in options) && options.rearg, + pristine = isLib ? func.runInContext() : undefined; + + var helpers = isLib ? func : { + 'ary': util.ary, + 'assign': util.assign, + 'clone': util.clone, + 'curry': util.curry, + 'forEach': util.forEach, + 'isArray': util.isArray, + 'isError': util.isError, + 'isFunction': util.isFunction, + 'isWeakMap': util.isWeakMap, + 'iteratee': util.iteratee, + 'keys': util.keys, + 'rearg': util.rearg, + 'toInteger': util.toInteger, + 'toPath': util.toPath + }; + + var ary = helpers.ary, + assign = helpers.assign, + clone = helpers.clone, + curry = helpers.curry, + each = helpers.forEach, + isArray = helpers.isArray, + isError = helpers.isError, + isFunction = helpers.isFunction, + isWeakMap = helpers.isWeakMap, + keys = helpers.keys, + rearg = helpers.rearg, + toInteger = helpers.toInteger, + toPath = helpers.toPath; + + var aryMethodKeys = keys(mapping.aryMethod); + + var wrappers = { + 'castArray': function(castArray) { + return function() { + var value = arguments[0]; + return isArray(value) + ? castArray(cloneArray(value)) + : castArray.apply(undefined, arguments); + }; + }, + 'iteratee': function(iteratee) { + return function() { + var func = arguments[0], + arity = arguments[1], + result = iteratee(func, arity), + length = result.length; + + if (config.cap && typeof arity == 'number') { + arity = arity > 2 ? (arity - 2) : 1; + return (length && length <= arity) ? result : baseAry(result, arity); + } + return result; + }; + }, + 'mixin': function(mixin) { + return function(source) { + var func = this; + if (!isFunction(func)) { + return mixin(func, Object(source)); + } + var pairs = []; + each(keys(source), function(key) { + if (isFunction(source[key])) { + pairs.push([key, func.prototype[key]]); + } + }); + + mixin(func, Object(source)); + + each(pairs, function(pair) { + var value = pair[1]; + if (isFunction(value)) { + func.prototype[pair[0]] = value; + } else { + delete func.prototype[pair[0]]; + } + }); + return func; + }; + }, + 'nthArg': function(nthArg) { + return function(n) { + var arity = n < 0 ? 1 : (toInteger(n) + 1); + return curry(nthArg(n), arity); + }; + }, + 'rearg': function(rearg) { + return function(func, indexes) { + var arity = indexes ? indexes.length : 0; + return curry(rearg(func, indexes), arity); + }; + }, + 'runInContext': function(runInContext) { + return function(context) { + return baseConvert(util, runInContext(context), options); + }; + } + }; + + /*--------------------------------------------------------------------------*/ + + /** + * Casts `func` to a function with an arity capped iteratee if needed. + * + * @private + * @param {string} name The name of the function to inspect. + * @param {Function} func The function to inspect. + * @returns {Function} Returns the cast function. + */ + function castCap(name, func) { + if (config.cap) { + var indexes = mapping.iterateeRearg[name]; + if (indexes) { + return iterateeRearg(func, indexes); + } + var n = !isLib && mapping.iterateeAry[name]; + if (n) { + return iterateeAry(func, n); + } + } + return func; + } + + /** + * Casts `func` to a curried function if needed. + * + * @private + * @param {string} name The name of the function to inspect. + * @param {Function} func The function to inspect. + * @param {number} n The arity of `func`. + * @returns {Function} Returns the cast function. + */ + function castCurry(name, func, n) { + return (forceCurry || (config.curry && n > 1)) + ? curry(func, n) + : func; + } + + /** + * Casts `func` to a fixed arity function if needed. + * + * @private + * @param {string} name The name of the function to inspect. + * @param {Function} func The function to inspect. + * @param {number} n The arity cap. + * @returns {Function} Returns the cast function. + */ + function castFixed(name, func, n) { + if (config.fixed && (forceFixed || !mapping.skipFixed[name])) { + var data = mapping.methodSpread[name], + start = data && data.start; + + return start === undefined ? ary(func, n) : flatSpread(func, start); + } + return func; + } + + /** + * Casts `func` to an rearged function if needed. + * + * @private + * @param {string} name The name of the function to inspect. + * @param {Function} func The function to inspect. + * @param {number} n The arity of `func`. + * @returns {Function} Returns the cast function. + */ + function castRearg(name, func, n) { + return (config.rearg && n > 1 && (forceRearg || !mapping.skipRearg[name])) + ? rearg(func, mapping.methodRearg[name] || mapping.aryRearg[n]) + : func; + } + + /** + * Creates a clone of `object` by `path`. + * + * @private + * @param {Object} object The object to clone. + * @param {Array|string} path The path to clone by. + * @returns {Object} Returns the cloned object. + */ + function cloneByPath(object, path) { + path = toPath(path); + + var index = -1, + length = path.length, + lastIndex = length - 1, + result = clone(Object(object)), + nested = result; + + while (nested != null && ++index < length) { + var key = path[index], + value = nested[key]; + + if (value != null && + !(isFunction(value) || isError(value) || isWeakMap(value))) { + nested[key] = clone(index == lastIndex ? value : Object(value)); + } + nested = nested[key]; + } + return result; + } + + /** + * Converts `lodash` to an immutable auto-curried iteratee-first data-last + * version with conversion `options` applied. + * + * @param {Object} [options] The options object. See `baseConvert` for more details. + * @returns {Function} Returns the converted `lodash`. + */ + function convertLib(options) { + return _.runInContext.convert(options)(undefined); + } + + /** + * Create a converter function for `func` of `name`. + * + * @param {string} name The name of the function to convert. + * @param {Function} func The function to convert. + * @returns {Function} Returns the new converter function. + */ + function createConverter(name, func) { + var realName = mapping.aliasToReal[name] || name, + methodName = mapping.remap[realName] || realName, + oldOptions = options; + + return function(options) { + var newUtil = isLib ? pristine : helpers, + newFunc = isLib ? pristine[methodName] : func, + newOptions = assign(assign({}, oldOptions), options); + + return baseConvert(newUtil, realName, newFunc, newOptions); + }; + } + + /** + * Creates a function that wraps `func` to invoke its iteratee, with up to `n` + * arguments, ignoring any additional arguments. + * + * @private + * @param {Function} func The function to cap iteratee arguments for. + * @param {number} n The arity cap. + * @returns {Function} Returns the new function. + */ + function iterateeAry(func, n) { + return overArg(func, function(func) { + return typeof func == 'function' ? baseAry(func, n) : func; + }); + } + + /** + * Creates a function that wraps `func` to invoke its iteratee with arguments + * arranged according to the specified `indexes` where the argument value at + * the first index is provided as the first argument, the argument value at + * the second index is provided as the second argument, and so on. + * + * @private + * @param {Function} func The function to rearrange iteratee arguments for. + * @param {number[]} indexes The arranged argument indexes. + * @returns {Function} Returns the new function. + */ + function iterateeRearg(func, indexes) { + return overArg(func, function(func) { + var n = indexes.length; + return baseArity(rearg(baseAry(func, n), indexes), n); + }); + } + + /** + * Creates a function that invokes `func` with its first argument transformed. + * + * @private + * @param {Function} func The function to wrap. + * @param {Function} transform The argument transform. + * @returns {Function} Returns the new function. + */ + function overArg(func, transform) { + return function() { + var length = arguments.length; + if (!length) { + return func(); + } + var args = Array(length); + while (length--) { + args[length] = arguments[length]; + } + var index = config.rearg ? 0 : (length - 1); + args[index] = transform(args[index]); + return func.apply(undefined, args); + }; + } + + /** + * Creates a function that wraps `func` and applys the conversions + * rules by `name`. + * + * @private + * @param {string} name The name of the function to wrap. + * @param {Function} func The function to wrap. + * @returns {Function} Returns the converted function. + */ + function wrap(name, func, placeholder) { + var result, + realName = mapping.aliasToReal[name] || name, + wrapped = func, + wrapper = wrappers[realName]; + + if (wrapper) { + wrapped = wrapper(func); + } + else if (config.immutable) { + if (mapping.mutate.array[realName]) { + wrapped = wrapImmutable(func, cloneArray); + } + else if (mapping.mutate.object[realName]) { + wrapped = wrapImmutable(func, createCloner(func)); + } + else if (mapping.mutate.set[realName]) { + wrapped = wrapImmutable(func, cloneByPath); + } + } + each(aryMethodKeys, function(aryKey) { + each(mapping.aryMethod[aryKey], function(otherName) { + if (realName == otherName) { + var data = mapping.methodSpread[realName], + afterRearg = data && data.afterRearg; + + result = afterRearg + ? castFixed(realName, castRearg(realName, wrapped, aryKey), aryKey) + : castRearg(realName, castFixed(realName, wrapped, aryKey), aryKey); + + result = castCap(realName, result); + result = castCurry(realName, result, aryKey); + return false; + } + }); + return !result; + }); + + result || (result = wrapped); + if (result == func) { + result = forceCurry ? curry(result, 1) : function() { + return func.apply(this, arguments); + }; + } + result.convert = createConverter(realName, func); + result.placeholder = func.placeholder = placeholder; + + return result; + } + + /*--------------------------------------------------------------------------*/ + + if (!isObj) { + return wrap(name, func, defaultHolder); + } + var _ = func; + + // Convert methods by ary cap. + var pairs = []; + each(aryMethodKeys, function(aryKey) { + each(mapping.aryMethod[aryKey], function(key) { + var func = _[mapping.remap[key] || key]; + if (func) { + pairs.push([key, wrap(key, func, _)]); + } + }); + }); + + // Convert remaining methods. + each(keys(_), function(key) { + var func = _[key]; + if (typeof func == 'function') { + var length = pairs.length; + while (length--) { + if (pairs[length][0] == key) { + return; + } + } + func.convert = createConverter(key, func); + pairs.push([key, func]); + } + }); + + // Assign to `_` leaving `_.prototype` unchanged to allow chaining. + each(pairs, function(pair) { + _[pair[0]] = pair[1]; + }); + + _.convert = convertLib; + _.placeholder = _; + + // Assign aliases. + each(keys(_), function(key) { + each(mapping.realToAlias[key] || [], function(alias) { + _[alias] = _[key]; + }); + }); + + return _; + } + + module.exports = baseConvert; + + +/***/ }), +/* 2 */ +/***/ (function(module, exports) { + + /** Used to map aliases to their real names. */ + exports.aliasToReal = { + + // Lodash aliases. + 'each': 'forEach', + 'eachRight': 'forEachRight', + 'entries': 'toPairs', + 'entriesIn': 'toPairsIn', + 'extend': 'assignIn', + 'extendAll': 'assignInAll', + 'extendAllWith': 'assignInAllWith', + 'extendWith': 'assignInWith', + 'first': 'head', + + // Methods that are curried variants of others. + 'conforms': 'conformsTo', + 'matches': 'isMatch', + 'property': 'get', + + // Ramda aliases. + '__': 'placeholder', + 'F': 'stubFalse', + 'T': 'stubTrue', + 'all': 'every', + 'allPass': 'overEvery', + 'always': 'constant', + 'any': 'some', + 'anyPass': 'overSome', + 'apply': 'spread', + 'assoc': 'set', + 'assocPath': 'set', + 'complement': 'negate', + 'compose': 'flowRight', + 'contains': 'includes', + 'dissoc': 'unset', + 'dissocPath': 'unset', + 'dropLast': 'dropRight', + 'dropLastWhile': 'dropRightWhile', + 'equals': 'isEqual', + 'identical': 'eq', + 'indexBy': 'keyBy', + 'init': 'initial', + 'invertObj': 'invert', + 'juxt': 'over', + 'omitAll': 'omit', + 'nAry': 'ary', + 'path': 'get', + 'pathEq': 'matchesProperty', + 'pathOr': 'getOr', + 'paths': 'at', + 'pickAll': 'pick', + 'pipe': 'flow', + 'pluck': 'map', + 'prop': 'get', + 'propEq': 'matchesProperty', + 'propOr': 'getOr', + 'props': 'at', + 'symmetricDifference': 'xor', + 'symmetricDifferenceBy': 'xorBy', + 'symmetricDifferenceWith': 'xorWith', + 'takeLast': 'takeRight', + 'takeLastWhile': 'takeRightWhile', + 'unapply': 'rest', + 'unnest': 'flatten', + 'useWith': 'overArgs', + 'where': 'conformsTo', + 'whereEq': 'isMatch', + 'zipObj': 'zipObject' + }; + + /** Used to map ary to method names. */ + exports.aryMethod = { + '1': [ + 'assignAll', 'assignInAll', 'attempt', 'castArray', 'ceil', 'create', + 'curry', 'curryRight', 'defaultsAll', 'defaultsDeepAll', 'floor', 'flow', + 'flowRight', 'fromPairs', 'invert', 'iteratee', 'memoize', 'method', 'mergeAll', + 'methodOf', 'mixin', 'nthArg', 'over', 'overEvery', 'overSome','rest', 'reverse', + 'round', 'runInContext', 'spread', 'template', 'trim', 'trimEnd', 'trimStart', + 'uniqueId', 'words', 'zipAll' + ], + '2': [ + 'add', 'after', 'ary', 'assign', 'assignAllWith', 'assignIn', 'assignInAllWith', + 'at', 'before', 'bind', 'bindAll', 'bindKey', 'chunk', 'cloneDeepWith', + 'cloneWith', 'concat', 'conformsTo', 'countBy', 'curryN', 'curryRightN', + 'debounce', 'defaults', 'defaultsDeep', 'defaultTo', 'delay', 'difference', + 'divide', 'drop', 'dropRight', 'dropRightWhile', 'dropWhile', 'endsWith', 'eq', + 'every', 'filter', 'find', 'findIndex', 'findKey', 'findLast', 'findLastIndex', + 'findLastKey', 'flatMap', 'flatMapDeep', 'flattenDepth', 'forEach', + 'forEachRight', 'forIn', 'forInRight', 'forOwn', 'forOwnRight', 'get', + 'groupBy', 'gt', 'gte', 'has', 'hasIn', 'includes', 'indexOf', 'intersection', + 'invertBy', 'invoke', 'invokeMap', 'isEqual', 'isMatch', 'join', 'keyBy', + 'lastIndexOf', 'lt', 'lte', 'map', 'mapKeys', 'mapValues', 'matchesProperty', + 'maxBy', 'meanBy', 'merge', 'mergeAllWith', 'minBy', 'multiply', 'nth', 'omit', + 'omitBy', 'overArgs', 'pad', 'padEnd', 'padStart', 'parseInt', 'partial', + 'partialRight', 'partition', 'pick', 'pickBy', 'propertyOf', 'pull', 'pullAll', + 'pullAt', 'random', 'range', 'rangeRight', 'rearg', 'reject', 'remove', + 'repeat', 'restFrom', 'result', 'sampleSize', 'some', 'sortBy', 'sortedIndex', + 'sortedIndexOf', 'sortedLastIndex', 'sortedLastIndexOf', 'sortedUniqBy', + 'split', 'spreadFrom', 'startsWith', 'subtract', 'sumBy', 'take', 'takeRight', + 'takeRightWhile', 'takeWhile', 'tap', 'throttle', 'thru', 'times', 'trimChars', + 'trimCharsEnd', 'trimCharsStart', 'truncate', 'union', 'uniqBy', 'uniqWith', + 'unset', 'unzipWith', 'without', 'wrap', 'xor', 'zip', 'zipObject', + 'zipObjectDeep' + ], + '3': [ + 'assignInWith', 'assignWith', 'clamp', 'differenceBy', 'differenceWith', + 'findFrom', 'findIndexFrom', 'findLastFrom', 'findLastIndexFrom', 'getOr', + 'includesFrom', 'indexOfFrom', 'inRange', 'intersectionBy', 'intersectionWith', + 'invokeArgs', 'invokeArgsMap', 'isEqualWith', 'isMatchWith', 'flatMapDepth', + 'lastIndexOfFrom', 'mergeWith', 'orderBy', 'padChars', 'padCharsEnd', + 'padCharsStart', 'pullAllBy', 'pullAllWith', 'rangeStep', 'rangeStepRight', + 'reduce', 'reduceRight', 'replace', 'set', 'slice', 'sortedIndexBy', + 'sortedLastIndexBy', 'transform', 'unionBy', 'unionWith', 'update', 'xorBy', + 'xorWith', 'zipWith' + ], + '4': [ + 'fill', 'setWith', 'updateWith' + ] + }; + + /** Used to map ary to rearg configs. */ + exports.aryRearg = { + '2': [1, 0], + '3': [2, 0, 1], + '4': [3, 2, 0, 1] + }; + + /** Used to map method names to their iteratee ary. */ + exports.iterateeAry = { + 'dropRightWhile': 1, + 'dropWhile': 1, + 'every': 1, + 'filter': 1, + 'find': 1, + 'findFrom': 1, + 'findIndex': 1, + 'findIndexFrom': 1, + 'findKey': 1, + 'findLast': 1, + 'findLastFrom': 1, + 'findLastIndex': 1, + 'findLastIndexFrom': 1, + 'findLastKey': 1, + 'flatMap': 1, + 'flatMapDeep': 1, + 'flatMapDepth': 1, + 'forEach': 1, + 'forEachRight': 1, + 'forIn': 1, + 'forInRight': 1, + 'forOwn': 1, + 'forOwnRight': 1, + 'map': 1, + 'mapKeys': 1, + 'mapValues': 1, + 'partition': 1, + 'reduce': 2, + 'reduceRight': 2, + 'reject': 1, + 'remove': 1, + 'some': 1, + 'takeRightWhile': 1, + 'takeWhile': 1, + 'times': 1, + 'transform': 2 + }; + + /** Used to map method names to iteratee rearg configs. */ + exports.iterateeRearg = { + 'mapKeys': [1], + 'reduceRight': [1, 0] + }; + + /** Used to map method names to rearg configs. */ + exports.methodRearg = { + 'assignInAllWith': [1, 0], + 'assignInWith': [1, 2, 0], + 'assignAllWith': [1, 0], + 'assignWith': [1, 2, 0], + 'differenceBy': [1, 2, 0], + 'differenceWith': [1, 2, 0], + 'getOr': [2, 1, 0], + 'intersectionBy': [1, 2, 0], + 'intersectionWith': [1, 2, 0], + 'isEqualWith': [1, 2, 0], + 'isMatchWith': [2, 1, 0], + 'mergeAllWith': [1, 0], + 'mergeWith': [1, 2, 0], + 'padChars': [2, 1, 0], + 'padCharsEnd': [2, 1, 0], + 'padCharsStart': [2, 1, 0], + 'pullAllBy': [2, 1, 0], + 'pullAllWith': [2, 1, 0], + 'rangeStep': [1, 2, 0], + 'rangeStepRight': [1, 2, 0], + 'setWith': [3, 1, 2, 0], + 'sortedIndexBy': [2, 1, 0], + 'sortedLastIndexBy': [2, 1, 0], + 'unionBy': [1, 2, 0], + 'unionWith': [1, 2, 0], + 'updateWith': [3, 1, 2, 0], + 'xorBy': [1, 2, 0], + 'xorWith': [1, 2, 0], + 'zipWith': [1, 2, 0] + }; + + /** Used to map method names to spread configs. */ + exports.methodSpread = { + 'assignAll': { 'start': 0 }, + 'assignAllWith': { 'start': 0 }, + 'assignInAll': { 'start': 0 }, + 'assignInAllWith': { 'start': 0 }, + 'defaultsAll': { 'start': 0 }, + 'defaultsDeepAll': { 'start': 0 }, + 'invokeArgs': { 'start': 2 }, + 'invokeArgsMap': { 'start': 2 }, + 'mergeAll': { 'start': 0 }, + 'mergeAllWith': { 'start': 0 }, + 'partial': { 'start': 1 }, + 'partialRight': { 'start': 1 }, + 'without': { 'start': 1 }, + 'zipAll': { 'start': 0 } + }; + + /** Used to identify methods which mutate arrays or objects. */ + exports.mutate = { + 'array': { + 'fill': true, + 'pull': true, + 'pullAll': true, + 'pullAllBy': true, + 'pullAllWith': true, + 'pullAt': true, + 'remove': true, + 'reverse': true + }, + 'object': { + 'assign': true, + 'assignAll': true, + 'assignAllWith': true, + 'assignIn': true, + 'assignInAll': true, + 'assignInAllWith': true, + 'assignInWith': true, + 'assignWith': true, + 'defaults': true, + 'defaultsAll': true, + 'defaultsDeep': true, + 'defaultsDeepAll': true, + 'merge': true, + 'mergeAll': true, + 'mergeAllWith': true, + 'mergeWith': true, + }, + 'set': { + 'set': true, + 'setWith': true, + 'unset': true, + 'update': true, + 'updateWith': true + } + }; + + /** Used to map real names to their aliases. */ + exports.realToAlias = (function() { + var hasOwnProperty = Object.prototype.hasOwnProperty, + object = exports.aliasToReal, + result = {}; + + for (var key in object) { + var value = object[key]; + if (hasOwnProperty.call(result, value)) { + result[value].push(key); + } else { + result[value] = [key]; + } + } + return result; + }()); + + /** Used to map method names to other names. */ + exports.remap = { + 'assignAll': 'assign', + 'assignAllWith': 'assignWith', + 'assignInAll': 'assignIn', + 'assignInAllWith': 'assignInWith', + 'curryN': 'curry', + 'curryRightN': 'curryRight', + 'defaultsAll': 'defaults', + 'defaultsDeepAll': 'defaultsDeep', + 'findFrom': 'find', + 'findIndexFrom': 'findIndex', + 'findLastFrom': 'findLast', + 'findLastIndexFrom': 'findLastIndex', + 'getOr': 'get', + 'includesFrom': 'includes', + 'indexOfFrom': 'indexOf', + 'invokeArgs': 'invoke', + 'invokeArgsMap': 'invokeMap', + 'lastIndexOfFrom': 'lastIndexOf', + 'mergeAll': 'merge', + 'mergeAllWith': 'mergeWith', + 'padChars': 'pad', + 'padCharsEnd': 'padEnd', + 'padCharsStart': 'padStart', + 'propertyOf': 'get', + 'rangeStep': 'range', + 'rangeStepRight': 'rangeRight', + 'restFrom': 'rest', + 'spreadFrom': 'spread', + 'trimChars': 'trim', + 'trimCharsEnd': 'trimEnd', + 'trimCharsStart': 'trimStart', + 'zipAll': 'zip' + }; + + /** Used to track methods that skip fixing their arity. */ + exports.skipFixed = { + 'castArray': true, + 'flow': true, + 'flowRight': true, + 'iteratee': true, + 'mixin': true, + 'rearg': true, + 'runInContext': true + }; + + /** Used to track methods that skip rearranging arguments. */ + exports.skipRearg = { + 'add': true, + 'assign': true, + 'assignIn': true, + 'bind': true, + 'bindKey': true, + 'concat': true, + 'difference': true, + 'divide': true, + 'eq': true, + 'gt': true, + 'gte': true, + 'isEqual': true, + 'lt': true, + 'lte': true, + 'matchesProperty': true, + 'merge': true, + 'multiply': true, + 'overArgs': true, + 'partial': true, + 'partialRight': true, + 'propertyOf': true, + 'random': true, + 'range': true, + 'rangeRight': true, + 'subtract': true, + 'zip': true, + 'zipObject': true, + 'zipObjectDeep': true + }; + + +/***/ }), +/* 3 */ +/***/ (function(module, exports) { + + /** + * The default argument placeholder value for methods. + * + * @type {Object} + */ + module.exports = {}; + + +/***/ }) +/******/ ]) +}); +; diff --git a/index.js b/index.js index 18fb1fb..4ba6551 100644 --- a/index.js +++ b/index.js @@ -35,7 +35,7 @@ const runner = { }).on('complete', function () { resolve(results); }) - .run({ 'async': true }); + .run({ 'async': false }); }) }, } @@ -113,6 +113,7 @@ async function main() { const result = await runBenchmark(bench) console.log(bench.name, 'results', JSON.stringify(result, null, 2)); } + console.log('Done...', file) } } diff --git a/package.json b/package.json index d2717fe..bf2bc14 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,8 @@ { "dependencies": { "fastify": "4.26.1", - "lodash": "4.17.21" + "lodash": "4.17.21", + "prettier": "3.2.5" }, "devDependencies": { "autocannon": "7.15.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2509af2..a1694bc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,9 @@ dependencies: lodash: specifier: 4.17.21 version: 4.17.21 + prettier: + specifier: 3.2.5 + version: 3.2.5 devDependencies: autocannon: @@ -33,7 +36,7 @@ packages: resolution: {integrity: sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA==} dependencies: ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) + ajv-formats: 2.1.1 fast-uri: 2.3.0 dev: false @@ -64,10 +67,8 @@ packages: resolution: {integrity: sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==} dev: false - /ajv-formats@2.1.1(ajv@8.12.0): + /ajv-formats@2.1.1: resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} - peerDependencies: - ajv: ^8.0.0 peerDependenciesMeta: ajv: optional: true @@ -274,7 +275,7 @@ packages: dependencies: '@fastify/merge-json-schemas': 0.1.1 ajv: 8.12.0 - ajv-formats: 2.1.1(ajv@8.12.0) + ajv-formats: 2.1.1 fast-deep-equal: 3.1.3 fast-uri: 2.3.0 json-schema-ref-resolver: 1.0.1 @@ -504,6 +505,12 @@ packages: resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} dev: true + /prettier@3.2.5: + resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + engines: {node: '>=14'} + hasBin: true + dev: false + /pretty-bytes@5.6.0: resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} engines: {node: '>=6'} diff --git a/src/prettier-benchmark.js b/src/prettier-benchmark.js new file mode 100644 index 0000000..ea61b12 --- /dev/null +++ b/src/prettier-benchmark.js @@ -0,0 +1,51 @@ +const fs = require('node:fs'); +const path = require('node:path'); +const prettier = require('prettier'); + +const payloads = [ + 'lodash.fp.js', +].map((file) => fs.readFileSync(path.join(__dirname, '..', 'fixtures', file), 'utf8')); + +module.exports = { + name: 'prettier', + type: 'operation', + operations: [ + { + name: 'format (semi=true)', + fn: () => { + let v = undefined; + for (const p of payloads) { + v= prettier.format(p, { semi: true, parser: 'babel' }); + } + return v; + }, + }, + // { + // name: 'format (singleQuote=true semi=true tabs=true)', + // fn: () => { + // let v = undefined; + // for (const p of payloads) { + // v = prettier.format( + // p, + // { singleQuote: true, semi: true, tabs: true, parser: 'babel' }, + // ); + // } + // return v; + // }, + // }, + // { + // name: 'format (singleQuote=false semi=false tabs=false)', + // fn: () => { + // let v = undefined; + // for (const p of payloads) { + // v = prettier.format( + // p, + // { singleQuote: false, semi: false, tabs: false, parser: 'babel' } + // ); + // } + // return v; + // }, + // }, + ], + benchmarker: 'benchmarkjs', +}; From f5231c7b9f732fe335a9d709cb1ee4d3143f9b1e Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Mon, 4 Mar 2024 13:15:58 -0300 Subject: [PATCH 04/12] src: use worker threads for each benchmark --- index.js | 113 +++----------------------------------- package.json | 1 + pnpm-lock.yaml | 30 ++++++++++ src/prettier-benchmark.js | 52 +++++++++--------- worker.js | 111 +++++++++++++++++++++++++++++++++++++ 5 files changed, 175 insertions(+), 132 deletions(-) create mode 100644 worker.js diff --git a/index.js b/index.js index 4ba6551..fcdf65c 100644 --- a/index.js +++ b/index.js @@ -1,117 +1,18 @@ const fs = require('node:fs/promises'); -const { setTimeout: delay } = require('node:timers/promises'); const path = require('node:path'); -const { spawn } = require('node:child_process'); -const assert = require('node:assert'); +const Piscina = require('piscina'); -const autocannon = require('autocannon'); -const Benchmark = require('benchmark'); - -const runner = { - autocannon: (opts) => { - return autocannon({ - url: `http://localhost:${opts.http.serverPort}`, - connections: 100, - pipelining: 1, - duration: 10 * opts.http.routes.length, - requests: opts.http.routes, - }) - }, - benchmarkjs: (opts) => { - const suite = new Benchmark.Suite; - - for (const operation of opts.operations) { - suite.add(operation.name, operation.fn); - } - - return new Promise((resolve) => { - const results = []; - suite.on('cycle', function(event) { - results.push({ - name: event.target.name, - opsSec: event.target.hz, - samples: event.target.cycles, - }); - }).on('complete', function () { - resolve(results); - }) - .run({ 'async': false }); - }) - }, -} - -const parser = { - autocannon: (settings, result) => { - return { - name: settings.name, - method: 'autocannon', - http: { - totalReq: asNumber(result.requests), - duration: result.duration, - errors: result.errors, - } - }; - }, - benchmarkjs: (settings, result) => { - return { - name: settings.name, - method: 'benchmarkjs', - operations: result, - } - } -} - -const ALLOWED_BENCHMARKER = ['autocannon', 'benchmarkjs']; - -function asNumber (stat) { - const result = Object.create(null) - for (const k of Object.keys(stat)) { - result[k] = stat[k].toLocaleString(undefined, { - // to show all digits - maximumFractionDigits: 20 - }) - } - return result -} - -function spawnServer(settings) { - const server = spawn( - process.execPath, - [settings.http.server], - { stdio: 'inherit' }, - ); - return server; -} - -async function runBenchmark(settings) { - assert.ok(ALLOWED_BENCHMARKER.includes(settings.benchmarker), 'Invalid settings.benchmarker'); - - let server = undefined; - if (settings.type === 'http') { - assert.ok(settings.http.server, 'HTTP Benchmark must have a server to be spawned'); - server = spawnServer(settings); - // TODO: replace this workaround to use IPC to know when server is up - await delay(1000); - } - - const benchRunner = runner[settings.benchmarker]; - const benchParser = parser[settings.benchmarker]; - const results = await benchRunner(settings); - if (server) { - server.kill('SIGINT'); - } - return benchParser(settings, results); -} +const piscina = new Piscina({ + filename: path.resolve(__dirname, 'worker.js') +}); async function main() { const files = await fs.readdir(path.join(__dirname, './src')); for (const file of files) { if (file.match(/.*-benchmark\.js$/)) { - const bench = require(path.join(__dirname, './src/', file)); - // TODO(rafaelgss): possibly should be more accurate to run each benchmark in - // a separate worker - const result = await runBenchmark(bench) - console.log(bench.name, 'results', JSON.stringify(result, null, 2)); + const benchFile = path.join(__dirname, './src/', file); + const result = await piscina.run(benchFile); + console.log('results', JSON.stringify(result, null, 2)); } console.log('Done...', file) } diff --git a/package.json b/package.json index bf2bc14..c2c0ffe 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "dependencies": { "fastify": "4.26.1", "lodash": "4.17.21", + "piscina": "4.4.0", "prettier": "3.2.5" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a1694bc..15262b3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -7,6 +7,9 @@ dependencies: lodash: specifier: 4.17.21 version: 4.17.21 + piscina: + specifier: 4.4.0 + version: 4.4.0 prettier: specifier: 3.2.5 version: 3.2.5 @@ -459,6 +462,27 @@ packages: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: false + /nice-napi@1.0.2: + resolution: {integrity: sha512-px/KnJAJZf5RuBGcfD+Sp2pAKq0ytz8j+1NehvgIGFkvtvFrDM3T8E4x/JJODXK9WZow8RRGrbA9QQ3hs+pDhA==} + os: ['!win32'] + requiresBuild: true + dependencies: + node-addon-api: 3.2.1 + node-gyp-build: 4.8.0 + dev: false + optional: true + + /node-addon-api@3.2.1: + resolution: {integrity: sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A==} + dev: false + optional: true + + /node-gyp-build@4.8.0: + resolution: {integrity: sha512-u6fs2AEUljNho3EYTJNBfImO5QTo/J/1Etd+NVdCj7qWKUSN/bSLkZwhDv7I+w/MSC6qJ4cknepkAYykDdK8og==} + hasBin: true + dev: false + optional: true + /on-exit-leak-free@2.1.2: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} @@ -501,6 +525,12 @@ packages: thread-stream: 2.4.1 dev: false + /piscina@4.4.0: + resolution: {integrity: sha512-+AQduEJefrOApE4bV7KRmp3N2JnnyErlVqq4P/jmko4FPz9Z877BCccl/iB3FdrWSUkvbGV9Kan/KllJgat3Vg==} + optionalDependencies: + nice-napi: 1.0.2 + dev: false + /platform@1.3.6: resolution: {integrity: sha512-fnWVljUchTro6RiCFvCXBbNhJc2NijN7oIQxbwsyL0buWJPG85v81ehlHI9fXrJsMNgTofEoWIQeClKpgxFLrg==} dev: true diff --git a/src/prettier-benchmark.js b/src/prettier-benchmark.js index ea61b12..a022d28 100644 --- a/src/prettier-benchmark.js +++ b/src/prettier-benchmark.js @@ -20,32 +20,32 @@ module.exports = { return v; }, }, - // { - // name: 'format (singleQuote=true semi=true tabs=true)', - // fn: () => { - // let v = undefined; - // for (const p of payloads) { - // v = prettier.format( - // p, - // { singleQuote: true, semi: true, tabs: true, parser: 'babel' }, - // ); - // } - // return v; - // }, - // }, - // { - // name: 'format (singleQuote=false semi=false tabs=false)', - // fn: () => { - // let v = undefined; - // for (const p of payloads) { - // v = prettier.format( - // p, - // { singleQuote: false, semi: false, tabs: false, parser: 'babel' } - // ); - // } - // return v; - // }, - // }, + { + name: 'format (singleQuote=true semi=true tabs=true)', + fn: () => { + let v = undefined; + for (const p of payloads) { + v = prettier.format( + p, + { singleQuote: true, semi: true, tabs: true, parser: 'babel' }, + ); + } + return v; + }, + }, + { + name: 'format (singleQuote=false semi=false tabs=false)', + fn: () => { + let v = undefined; + for (const p of payloads) { + v = prettier.format( + p, + { singleQuote: false, semi: false, tabs: false, parser: 'babel' } + ); + } + return v; + }, + }, ], benchmarker: 'benchmarkjs', }; diff --git a/worker.js b/worker.js new file mode 100644 index 0000000..daaf84e --- /dev/null +++ b/worker.js @@ -0,0 +1,111 @@ +const { spawn } = require('node:child_process'); +const assert = require('node:assert'); + +const autocannon = require('autocannon'); +const Benchmark = require('benchmark'); + +const { setTimeout: delay } = require('node:timers/promises'); + +const runner = { + autocannon: (opts) => { + return autocannon({ + url: `http://localhost:${opts.http.serverPort}`, + connections: 100, + pipelining: 1, + duration: 10 * opts.http.routes.length, + requests: opts.http.routes, + }) + }, + benchmarkjs: (opts) => { + const suite = new Benchmark.Suite; + + for (const operation of opts.operations) { + suite.add(operation.name, operation.fn); + } + + return new Promise((resolve) => { + const results = []; + suite.on('cycle', function(event) { + results.push({ + name: event.target.name, + opsSec: event.target.hz, + samples: event.target.cycles, + }); + }).on('complete', function () { + resolve(results); + }) + .run({ 'async': false }); + }) + }, +} + +const parser = { + autocannon: (settings, result) => { + return { + name: settings.name, + method: 'autocannon', + http: { + totalReq: asNumber(result.requests), + duration: result.duration, + errors: result.errors, + } + }; + }, + benchmarkjs: (settings, result) => { + return { + name: settings.name, + method: 'benchmarkjs', + operations: result, + } + } +} + +const ALLOWED_BENCHMARKER = ['autocannon', 'benchmarkjs']; + +function asNumber (stat) { + const result = Object.create(null) + for (const k of Object.keys(stat)) { + result[k] = stat[k].toLocaleString(undefined, { + // to show all digits + maximumFractionDigits: 20 + }) + } + return result +} + +function spawnServer(settings) { + const server = spawn( + process.execPath, + [settings.http.server], + { stdio: 'inherit' }, + ); + return server; +} + +async function runBenchmark(settings) { + assert.ok(ALLOWED_BENCHMARKER.includes(settings.benchmarker), 'Invalid settings.benchmarker'); + + let server = undefined; + if (settings.type === 'http') { + assert.ok(settings.http.server, 'HTTP Benchmark must have a server to be spawned'); + server = spawnServer(settings); + // TODO: replace this workaround to use IPC to know when server is up + await delay(1000); + } + + const benchRunner = runner[settings.benchmarker]; + const benchParser = parser[settings.benchmarker]; + const results = await benchRunner(settings); + if (server) { + server.kill('SIGINT'); + } + return benchParser(settings, results); +} + +async function main (benchFile) { + const bench = require(benchFile); + const result = await runBenchmark(bench); + return result; +} + +module.exports = main; From a38617f681de854e04cf2a3f8e2ec5cc26cbe942 Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Mon, 4 Mar 2024 13:52:16 -0300 Subject: [PATCH 05/12] feat: add babel benchmark --- README.md | 2 +- package.json | 1 + pnpm-lock.yaml | 8 ++++++++ src/babel-benchmark.js | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/babel-benchmark.js diff --git a/README.md b/README.md index bd261f0..9102fa3 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ packages operations. - [x] lodash - [x] prettier - [ ] webpack -- [ ] babel +- [x] babel - [ ] moment - [ ] dotenv - [ ] pinojs diff --git a/package.json b/package.json index c2c0ffe..244aaf3 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,6 @@ { "dependencies": { + "@babel/standalone": "7.24.0", "fastify": "4.26.1", "lodash": "4.17.21", "piscina": "4.4.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 15262b3..044cf9e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,6 +1,9 @@ lockfileVersion: '6.0' dependencies: + '@babel/standalone': + specifier: 7.24.0 + version: 7.24.0 fastify: specifier: 4.26.1 version: 4.26.1 @@ -28,6 +31,11 @@ packages: resolution: {integrity: sha512-ulkCYfFbYj01ie1MDOyxv2F6SpRN1TOj7fQxbP07D6HmeR+gr2JLSmINKjga2emB+b1L2KGrFKBTc+e00p54nw==} dev: true + /@babel/standalone@7.24.0: + resolution: {integrity: sha512-yIZ/X3EAASgX/MW1Bn8iZKxCwixgYJAUaIScoZ9C6Gapw5l3eKIbtVSgO/IGldQed9QXm22yurKVWyWj5/j+SQ==} + engines: {node: '>=6.9.0'} + dev: false + /@colors/colors@1.5.0: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} diff --git a/src/babel-benchmark.js b/src/babel-benchmark.js new file mode 100644 index 0000000..2b11a4d --- /dev/null +++ b/src/babel-benchmark.js @@ -0,0 +1,35 @@ +const fs = require('node:fs'); +const path = require('node:path'); +const Babel = require('@babel/standalone'); + +const payloads = [ + 'lodash.fp.js', +].map((file) => fs.readFileSync(path.join(__dirname, '..', 'fixtures', file), 'utf8')); + +module.exports = { + name: 'babel', + type: 'operation', + operations: [ + { + name: 'transform (code=true ast=true)', + fn: () => { + let v = undefined; + for (const p of payloads) { + v = Babel.transform(p, { code: true, ast: true }).code; + } + return v; + }, + }, + { + name: 'transform (code=false)', + fn: () => { + let v = undefined; + for (const p of payloads) { + v = Babel.transform(p, { code: false }).code; + } + return v; + }, + } + ], + benchmarker: 'benchmarkjs', +}; From c422d913a0cceb54c238ee4588d3b6ccf5229908 Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Mon, 4 Mar 2024 14:07:52 -0300 Subject: [PATCH 06/12] feat: add moment benchmark --- README.md | 2 +- index.js | 4 ++-- package.json | 1 + pnpm-lock.yaml | 7 +++++++ src/moment-benchmark.js | 33 +++++++++++++++++++++++++++++++++ 5 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 src/moment-benchmark.js diff --git a/README.md b/README.md index 9102fa3..d84fc3b 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ packages operations. - [x] prettier - [ ] webpack - [x] babel -- [ ] moment +- [x] moment - [ ] dotenv - [ ] pinojs - [ ] winston diff --git a/index.js b/index.js index fcdf65c..11e7eb4 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,8 @@ const path = require('node:path'); const Piscina = require('piscina'); const piscina = new Piscina({ - filename: path.resolve(__dirname, 'worker.js') + filename: path.resolve(__dirname, 'worker.js'), + maxQueue: 1, }); async function main() { @@ -14,7 +15,6 @@ async function main() { const result = await piscina.run(benchFile); console.log('results', JSON.stringify(result, null, 2)); } - console.log('Done...', file) } } diff --git a/package.json b/package.json index 244aaf3..f47f794 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "@babel/standalone": "7.24.0", "fastify": "4.26.1", "lodash": "4.17.21", + "moment": "2.30.1", "piscina": "4.4.0", "prettier": "3.2.5" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 044cf9e..923a1a5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,6 +10,9 @@ dependencies: lodash: specifier: 4.17.21 version: 4.17.21 + moment: + specifier: 2.30.1 + version: 2.30.1 piscina: specifier: 4.4.0 version: 4.4.0 @@ -466,6 +469,10 @@ packages: resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} dev: true + /moment@2.30.1: + resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} + dev: false + /ms@2.1.2: resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} dev: false diff --git a/src/moment-benchmark.js b/src/moment-benchmark.js new file mode 100644 index 0000000..fdaa070 --- /dev/null +++ b/src/moment-benchmark.js @@ -0,0 +1,33 @@ +const moment = require('moment'); + +module.exports = { + name: 'moment', + type: 'operation', + operations: [ + { + name: 'format (full)', + fn: () => { + return moment().format('MMMM Do YYYY, h:mm:ss a'); + }, + }, + { + name: 'format', + fn: () => { + return moment().format(); + }, + }, + { + name: 'fromNow (YYYYMMDD)', + fn: () => { + return moment('20111031', 'YYYYMMDD').fromNow(); + }, + }, + { + name: 'subtract (10)', + fn: () => { + return moment().subtract(10, 'days').calendar(); + }, + }, + ], + benchmarker: 'benchmarkjs', +}; From 866a54d8f3f1cff3345b8cae793c2b2059fadd1e Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Mon, 4 Mar 2024 14:23:31 -0300 Subject: [PATCH 07/12] feat: add dotenv benchmark --- README.md | 2 +- fixtures/.env.sample | 41 +++++++++++++++++++++++++++++++++++++++++ package.json | 1 + pnpm-lock.yaml | 8 ++++++++ src/dotenv-benchmark.js | 18 ++++++++++++++++++ 5 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 fixtures/.env.sample create mode 100644 src/dotenv-benchmark.js diff --git a/README.md b/README.md index d84fc3b..3111f2e 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ packages operations. - [ ] webpack - [x] babel - [x] moment -- [ ] dotenv +- [x] dotenv - [ ] pinojs - [ ] winston - [ ] helmet diff --git a/fixtures/.env.sample b/fixtures/.env.sample new file mode 100644 index 0000000..8afd3a6 --- /dev/null +++ b/fixtures/.env.sample @@ -0,0 +1,41 @@ +# Database Configuration +DB_HOST=localhost +DB_PORT=5432 +DB_USERNAME=myusername +DB_PASSWORD=mypassword +DB_NAME=mydatabase + +# API Keys +API_KEY_1=your_api_key_1 +API_KEY_2=your_api_key_2 +API_KEY_3=your_api_key_3 + +# Server Configuration +SERVER_HOST=127.0.0.1 +SERVER_PORT=8080 + +# Logging Configuration +LOG_LEVEL=debug +LOG_PATH=/var/log/myapp.log + +# Authentication +JWT_SECRET=your_jwt_secret +OAUTH_CLIENT_ID=your_oauth_client_id +OAUTH_CLIENT_SECRET=your_oauth_client_secret + +# Email Configuration +EMAIL_HOST=smtp.example.com +EMAIL_PORT=587 +EMAIL_USERNAME=myemail@example.com +EMAIL_PASSWORD=myemailpassword +EMAIL_FROM=myemail@example.com + +# AWS Configuration +AWS_ACCESS_KEY_ID=your_aws_access_key_id +AWS_SECRET_ACCESS_KEY=your_aws_secret_access_key +AWS_REGION=us-east-1 +S3_BUCKET=my-s3-bucket + +# Miscellaneous +DEBUG_MODE=true +CACHE_ENABLED=true diff --git a/package.json b/package.json index f47f794..821acad 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "dependencies": { "@babel/standalone": "7.24.0", + "dotenv": "16.4.5", "fastify": "4.26.1", "lodash": "4.17.21", "moment": "2.30.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 923a1a5..2fb4319 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,9 @@ dependencies: '@babel/standalone': specifier: 7.24.0 version: 7.24.0 + dotenv: + specifier: 16.4.5 + version: 16.4.5 fastify: specifier: 4.26.1 version: 4.26.1 @@ -258,6 +261,11 @@ packages: engines: {node: '>=0.4.0'} dev: true + /dotenv@16.4.5: + resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} + engines: {node: '>=12'} + dev: false + /emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true diff --git a/src/dotenv-benchmark.js b/src/dotenv-benchmark.js new file mode 100644 index 0000000..95ce1d8 --- /dev/null +++ b/src/dotenv-benchmark.js @@ -0,0 +1,18 @@ +const path = require('node:path'); +const dotenv = require('dotenv'); + +const envFile = path.join(__dirname, '..', 'fixtures', '.env.sample'); + +module.exports = { + name: 'dotenv', + type: 'operation', + operations: [ + { + name: 'config', + fn: () => { + return dotenv.config({ path: envFile }); + }, + }, + ], + benchmarker: 'benchmarkjs', +}; From a4cbc8fbb94ae532d21323f3fc2cca4ee92b3426 Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Mon, 4 Mar 2024 14:48:50 -0300 Subject: [PATCH 08/12] feat: add pinojs benchmark --- README.md | 2 +- package.json | 1 + pnpm-lock.yaml | 3 +++ src/pino-benchmark.js | 18 ++++++++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/pino-benchmark.js diff --git a/README.md b/README.md index 3111f2e..9c8aaeb 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ packages operations. - [x] babel - [x] moment - [x] dotenv -- [ ] pinojs +- [x] pinojs - [ ] winston - [ ] helmet - [ ] node-sass diff --git a/package.json b/package.json index 821acad..79def5c 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "fastify": "4.26.1", "lodash": "4.17.21", "moment": "2.30.1", + "pino": "8.19.0", "piscina": "4.4.0", "prettier": "3.2.5" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2fb4319..64b16cd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,6 +16,9 @@ dependencies: moment: specifier: 2.30.1 version: 2.30.1 + pino: + specifier: 8.19.0 + version: 8.19.0 piscina: specifier: 4.4.0 version: 4.4.0 diff --git a/src/pino-benchmark.js b/src/pino-benchmark.js new file mode 100644 index 0000000..f0c696e --- /dev/null +++ b/src/pino-benchmark.js @@ -0,0 +1,18 @@ +const pino = require('pino'); +const logger = pino(pino.destination('/dev/null')); + +module.exports = { + name: 'pinojs', + type: 'operation', + operations: [ + { + name: 'info (10x)', + fn: () => { + for (let i = 0; i < 10; ++i) { + logger.info('hello world'); + } + }, + }, + ], + benchmarker: 'benchmarkjs', +}; From 4adbb7557a017d6cdb3ab956f46f49235dca179d Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Mon, 4 Mar 2024 15:10:59 -0300 Subject: [PATCH 09/12] feat: add winston benchmark --- README.md | 2 +- package.json | 3 +- pnpm-lock.yaml | 161 ++++++++++++++++++++++++++++++++++++++- src/winston-benchmark.js | 26 +++++++ 4 files changed, 189 insertions(+), 3 deletions(-) create mode 100644 src/winston-benchmark.js diff --git a/README.md b/README.md index 9c8aaeb..8521251 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ packages operations. - [x] moment - [x] dotenv - [x] pinojs -- [ ] winston +- [x] winston - [ ] helmet - [ ] node-sass - [ ] underscore diff --git a/package.json b/package.json index 79def5c..0822001 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "moment": "2.30.1", "pino": "8.19.0", "piscina": "4.4.0", - "prettier": "3.2.5" + "prettier": "3.2.5", + "winston": "3.12.0" }, "devDependencies": { "autocannon": "7.15.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 64b16cd..abf8151 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,6 +25,9 @@ dependencies: prettier: specifier: 3.2.5 version: 3.2.5 + winston: + specifier: 3.12.0 + version: 3.12.0 devDependencies: autocannon: @@ -52,6 +55,19 @@ packages: dev: true optional: true + /@colors/colors@1.6.0: + resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} + engines: {node: '>=0.1.90'} + dev: false + + /@dabh/diagnostics@2.0.3: + resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} + dependencies: + colorspace: 1.1.4 + enabled: 2.0.0 + kuler: 2.0.0 + dev: false + /@fastify/ajv-compiler@3.5.0: resolution: {integrity: sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA==} dependencies: @@ -76,6 +92,10 @@ packages: fast-deep-equal: 3.1.3 dev: false + /@types/triple-beam@1.3.5: + resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + dev: false + /abort-controller@3.0.0: resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} engines: {node: '>=6.5'} @@ -121,6 +141,10 @@ packages: resolution: {integrity: sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==} dev: false + /async@3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + dev: false + /asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} dev: true @@ -215,6 +239,12 @@ packages: '@colors/colors': 1.5.0 dev: true + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: false + /color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} @@ -222,15 +252,39 @@ packages: color-name: 1.1.4 dev: true + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: false + /color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} - dev: true + + /color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + dev: false /color-support@1.1.3: resolution: {integrity: sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==} hasBin: true dev: true + /color@3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + dependencies: + color-convert: 1.9.3 + color-string: 1.9.1 + dev: false + + /colorspace@1.1.4: + resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} + dependencies: + color: 3.2.1 + text-hex: 1.0.0 + dev: false + /combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -273,6 +327,10 @@ packages: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} dev: true + /enabled@2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + dev: false + /event-target-shim@5.0.1: resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} engines: {node: '>=6'} @@ -351,6 +409,10 @@ packages: reusify: 1.0.4 dev: false + /fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + dev: false + /find-my-way@8.1.0: resolution: {integrity: sha512-41QwjCGcVTODUmLLqTMeoHeiozbMXYMAE1CKFiDyi9zVZ2Vjh0yz3MF0WQZoIb+cmzP/XlbFjlF2NtJmvZHznA==} engines: {node: '>=14'} @@ -360,6 +422,10 @@ packages: safe-regex2: 2.0.0 dev: false + /fn.name@1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + dev: false + /form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -411,16 +477,29 @@ packages: /ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + /ipaddr.js@1.9.1: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} dev: false + /is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + dev: false + /is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} dev: true + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: false + /json-schema-ref-resolver@1.0.1: resolution: {integrity: sha512-EJAj1pgHc1hxF6vo2Z3s69fMjO1INq6eGHXZ8Z6wCQeldCuwxGK9Sxf4/cScGn3FZubCVUehfWtcDM/PLteCQw==} dependencies: @@ -431,6 +510,10 @@ packages: resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} dev: false + /kuler@2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + dev: false + /light-my-request@5.11.1: resolution: {integrity: sha512-KXAh2m6VRlkWCk2KfmHE7tLBXKh30JE0tXUJY4dNxje4oLmPKUqlUfImiEQZLphx+Z9KTQcVv4DjGnJxkVOIbA==} dependencies: @@ -454,6 +537,18 @@ packages: /lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + /logform@2.6.0: + resolution: {integrity: sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==} + engines: {node: '>= 12.0.0'} + dependencies: + '@colors/colors': 1.6.0 + '@types/triple-beam': 1.3.5 + fecha: 4.2.3 + ms: 2.1.2 + safe-stable-stringify: 2.4.3 + triple-beam: 1.4.1 + dev: false + /lru-cache@6.0.0: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} @@ -519,6 +614,12 @@ packages: engines: {node: '>=9.4.0 || ^8.9.4'} dev: true + /one-time@1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + dependencies: + fn.name: 1.1.0 + dev: false + /pako@1.0.11: resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} dev: true @@ -607,6 +708,15 @@ packages: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} dev: false + /readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + dev: false + /readable-stream@4.5.2: resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -680,6 +790,12 @@ packages: resolution: {integrity: sha512-RVnVQxTXuerk653XfuliOxBP81Sf0+qfQE73LIYKcyMYHG94AuH0kgrQpRDuTZnSmjpysHmzxJXKNfa6PjFhyQ==} dev: false + /simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + dependencies: + is-arrayish: 0.3.2 + dev: false + /sonic-boom@3.8.0: resolution: {integrity: sha512-ybz6OYOUjoQQCQ/i4LU8kaToD8ACtYP+Cj5qd2AO36bwbdewxWJ3ArmJ2cr6AvxlL2o0PqnCcPGUgkILbfkaCA==} dependencies: @@ -691,6 +807,10 @@ packages: engines: {node: '>= 10.x'} dev: false + /stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + dev: false + /string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -726,6 +846,10 @@ packages: has-flag: 4.0.0 dev: true + /text-hex@1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + dev: false + /thread-stream@2.4.1: resolution: {integrity: sha512-d/Ex2iWd1whipbT681JmTINKw0ZwOUBZm7+Gjs64DHuX34mmw8vJL2bFAaNacaW72zYiTJxSHi5abUuOi5nsfg==} dependencies: @@ -742,12 +866,21 @@ packages: engines: {node: '>=12'} dev: false + /triple-beam@1.4.1: + resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} + engines: {node: '>= 14.0.0'} + dev: false + /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: punycode: 2.3.1 dev: false + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false + /uuid-parse@1.1.0: resolution: {integrity: sha512-OdmXxA8rDsQ7YpNVbKSJkNzTw2I+S5WsbMDnCtIWSQaosNAcWtFuI/YK1TjzUI6nbkgiqEyh8gWngfcv8Asd9A==} dev: true @@ -757,6 +890,32 @@ packages: hasBin: true dev: true + /winston-transport@4.7.0: + resolution: {integrity: sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==} + engines: {node: '>= 12.0.0'} + dependencies: + logform: 2.6.0 + readable-stream: 3.6.2 + triple-beam: 1.4.1 + dev: false + + /winston@3.12.0: + resolution: {integrity: sha512-OwbxKaOlESDi01mC9rkM0dQqQt2I8DAUMRLZ/HpbwvDXm85IryEHgoogy5fziQy38PntgZsLlhAYHz//UPHZ5w==} + engines: {node: '>= 12.0.0'} + dependencies: + '@colors/colors': 1.6.0 + '@dabh/diagnostics': 2.0.3 + async: 3.2.5 + is-stream: 2.0.1 + logform: 2.6.0 + one-time: 1.0.0 + readable-stream: 3.6.2 + safe-stable-stringify: 2.4.3 + stack-trace: 0.0.10 + triple-beam: 1.4.1 + winston-transport: 4.7.0 + dev: false + /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} diff --git a/src/winston-benchmark.js b/src/winston-benchmark.js new file mode 100644 index 0000000..59bc540 --- /dev/null +++ b/src/winston-benchmark.js @@ -0,0 +1,26 @@ +const fs = require('node:fs'); +const winston = require('winston'); + +const logger = winston.createLogger({ + transports: [ + new winston.transports.Stream({ + stream: fs.createWriteStream('/dev/null'), + }), + ], +}); + +module.exports = { + name: 'winston', + type: 'operation', + operations: [ + { + name: 'info (10x)', + fn: () => { + for (let i = 0; i < 10; ++i) { + logger.log('info', 'hello world'); + } + }, + }, + ], + benchmarker: 'benchmarkjs', +}; From 1979fe4b9fad18f97e33d71ff2b232022bdf3243 Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Mon, 4 Mar 2024 15:11:12 -0300 Subject: [PATCH 10/12] src: update worker old space size due to prettier --- index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/index.js b/index.js index 11e7eb4..65b7d6f 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,11 @@ const Piscina = require('piscina'); const piscina = new Piscina({ filename: path.resolve(__dirname, 'worker.js'), + resourceLimits: { + // 16GiB for each Worker (1 per run) + // This was required due to prettier benchmark + maxOldGenerationSizeMb: 16384, + }, maxQueue: 1, }); From 8dfc193d46f98babdc6b948fa292354c56e6077c Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Mon, 4 Mar 2024 15:29:20 -0300 Subject: [PATCH 11/12] feat: add underscore benchmark --- README.md | 2 +- package.json | 1 + pnpm-lock.yaml | 7 +++++++ src/underscore-benchmark.js | 39 +++++++++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/underscore-benchmark.js diff --git a/README.md b/README.md index 8521251..fc948bf 100644 --- a/README.md +++ b/README.md @@ -16,5 +16,5 @@ packages operations. - [x] winston - [ ] helmet - [ ] node-sass -- [ ] underscore +- [x] underscore - [ ] minify diff --git a/package.json b/package.json index 0822001..5262196 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,7 @@ "pino": "8.19.0", "piscina": "4.4.0", "prettier": "3.2.5", + "underscore": "1.13.6", "winston": "3.12.0" }, "devDependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index abf8151..74f4871 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,6 +25,9 @@ dependencies: prettier: specifier: 3.2.5 version: 3.2.5 + underscore: + specifier: 1.13.6 + version: 1.13.6 winston: specifier: 3.12.0 version: 3.12.0 @@ -871,6 +874,10 @@ packages: engines: {node: '>= 14.0.0'} dev: false + /underscore@1.13.6: + resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} + dev: false + /uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} dependencies: diff --git a/src/underscore-benchmark.js b/src/underscore-benchmark.js new file mode 100644 index 0000000..6386149 --- /dev/null +++ b/src/underscore-benchmark.js @@ -0,0 +1,39 @@ +const underscore = require('underscore'); + +module.exports = { + name: 'underscore', + type: 'operation', + operations: [ + { + name: '.chunk', + fn: () => { + underscore.chunk(['a', 'b', 'c', 'd'], 2); + }, + }, + { + name: '.groupBy', + fn: () => { + underscore.groupBy([6.1, 4.2, 6.3], Math.floor); + }, + }, + { + name: '.includes', + fn: () => { + underscore.includes({ 'a': 1, 'b': 2 }, 1); + }, + }, + { + name: '.orderBy', + fn: () => { + const users = [ + { 'user': 'fred', 'age': 48 }, + { 'user': 'barney', 'age': 34 }, + { 'user': 'fred', 'age': 40 }, + { 'user': 'barney', 'age': 36 } + ]; + underscore.sortBy(users, ['user', 'age'], ['asc', 'desc']); + } + } + ], + benchmarker: 'benchmarkjs', +}; From 8f04cf236cb63b80892ff5a3cd0a05657f777146 Mon Sep 17 00:00:00 2001 From: RafaelGSS Date: Mon, 4 Mar 2024 15:32:15 -0300 Subject: [PATCH 12/12] src: drop webpack,minify,node-sass It doesn't seem to make sense to benchmark it in a Node.js|NS runtime. --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index fc948bf..62dab12 100644 --- a/README.md +++ b/README.md @@ -8,13 +8,9 @@ packages operations. - [x] fastify - [x] lodash - [x] prettier -- [ ] webpack - [x] babel - [x] moment - [x] dotenv - [x] pinojs - [x] winston -- [ ] helmet -- [ ] node-sass - [x] underscore -- [ ] minify