Toggle navigation
MeasureThat.net
Create a benchmark
Tools
Feedback
FAQ
Register
Log In
Run results for:
fast-sort js vs ts
TS compiled fast-sort vs js modified
Go to the benchmark
Embed
Embed Benchmark Result
Run details:
User agent:
Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Mobile Safari/537.36
Browser:
Chrome Mobile 121
Operating system:
Android
Device Platform:
Mobile
Date tested:
2 years ago
Test name
Executions per second
JS fast-sort
24.1 Ops/sec
TS fast-sort
11.5 Ops/sec
Script Preparation code:
const fastSortTS = () => { // >>> INTERFACES <<< // >>> HELPERS <<< const castComparer = (comparer) => (a, b, order) => comparer(a, b, order) * order; const throwInvalidConfigErrorIfTrue = function(condition, context) { if (condition) throw Error(`Invalid sort config: ${context}`); }; const unpackObjectSorter = function(sortByObj) { const { asc, desc } = sortByObj || {}; const order = asc ? 1 : -1; const sortBy = (asc || desc); // Validate object config throwInvalidConfigErrorIfTrue(!sortBy, 'Expected `asc` or `desc` property'); throwInvalidConfigErrorIfTrue(asc && desc, 'Ambiguous object with `asc` and `desc` config properties'); const comparer = sortByObj.comparer && castComparer(sortByObj.comparer); return { order, sortBy, comparer }; }; // >>> SORTERS <<< const multiPropertySorterProvider = function(defaultComparer) { return function multiPropertySorter(sortBy, sortByArr, depth, order, comparer, a, b) { let valA; let valB; if (typeof sortBy === 'string') { valA = a[sortBy]; valB = b[sortBy]; } else if (typeof sortBy === 'function') { valA = sortBy(a); valB = sortBy(b); } else { const objectSorterConfig = unpackObjectSorter(sortBy); return multiPropertySorter(objectSorterConfig.sortBy, sortByArr, depth, objectSorterConfig.order, objectSorterConfig.comparer || defaultComparer, a, b); } const equality = comparer(valA, valB, order); if ((equality === 0 || (valA == null && valB == null)) && sortByArr.length > depth) { return multiPropertySorter(sortByArr[depth], sortByArr, depth + 1, order, comparer, a, b); } return equality; }; }; function getSortStrategy(sortBy, comparer, order) { // Flat array sorter if (sortBy === undefined || sortBy === true) { return (a, b) => comparer(a, b, order); } // Sort list of objects by single object key if (typeof sortBy === 'string') { throwInvalidConfigErrorIfTrue(sortBy.includes('.'), 'String syntax not allowed for nested properties.'); return (a, b) => comparer(a[sortBy], b[sortBy], order); } // Sort list of objects by single function sorter if (typeof sortBy === 'function') { return (a, b) => comparer(sortBy(a), sortBy(b), order); } // Sort by multiple properties if (Array.isArray(sortBy)) { const multiPropSorter = multiPropertySorterProvider(comparer); return (a, b) => multiPropSorter(sortBy[0], sortBy, 1, order, comparer, a, b); } // Unpack object config to get actual sorter strategy const objectSorterConfig = unpackObjectSorter(sortBy); return getSortStrategy(objectSorterConfig.sortBy, objectSorterConfig.comparer || comparer, objectSorterConfig.order); } const sortArray = function(order, ctx, sortBy, comparer) { if (!Array.isArray(ctx)) { return ctx; } // Unwrap sortBy if array with only 1 value to get faster sort strategy if (Array.isArray(sortBy) && sortBy.length < 2) { [sortBy] = sortBy; } return ctx.sort(getSortStrategy(sortBy, comparer, order)); }; function createNewSortInstance(opts) { const comparer = castComparer(opts.comparer); return function(arrayToSort) { const ctx = Array.isArray(arrayToSort) && !opts.inPlaceSorting ? arrayToSort.slice() : arrayToSort; return { asc(sortBy) { return sortArray(1, ctx, sortBy, comparer); }, desc(sortBy) { return sortArray(-1, ctx, sortBy, comparer); }, by(sortBy) { return sortArray(1, ctx, sortBy, comparer); }, }; }; } const defaultComparer = (a, b, order) => { if (a == null) return order; if (b == null) return -order; if (typeof a !== typeof b) { return typeof a < typeof b ? -1 : 1; } if (a < b) return -1; if (a > b) return 1; return 0; }; return createNewSortInstance({ comparer: defaultComparer, }); } const { isArray } = Array const castComparer = (comparer) => (a, b, order) => comparer(a, b, order) * order const throwInvalidConfigErrorIfTrue = (condition, context) => { if (condition) throw Error(`Invalid sort config: ${context}`) } const unpackObjectSorter = (sortByObj) => { const { asc, desc } = sortByObj || {} const sortBy = (asc || desc) // Validate object config throwInvalidConfigErrorIfTrue(!sortBy, 'Expected `asc` or `desc` property') throwInvalidConfigErrorIfTrue(asc && desc, 'Ambiguous object with `asc` and `desc` config properties') return { order: asc ? 1 : -1, sortBy, comparer: sortByObj.comparer && castComparer(sortByObj.comparer) } } // >>> SORTERS <<< const multiPropertySorterProvider = (defaultComparer) => { const multiPropertySorter = (sortBy, sortByArr, depth, order, comparer, a, b) => { const type = typeof sortBy let valA; let valB; if (type === 'string') { valA = a[sortBy]; valB = b[sortBy]; } else if (type === 'function') { valA = sortBy(a); valB = sortBy(b); } else { const objectSorterConfig = unpackObjectSorter(sortBy); return multiPropertySorter(objectSorterConfig.sortBy, sortByArr, depth, objectSorterConfig.order, objectSorterConfig.comparer || defaultComparer, a, b); } const equality = comparer(valA, valB, order); if ((equality === 0 || (valA == null && valB == null)) && sortByArr.length > depth) { return multiPropertySorter(sortByArr[depth], sortByArr, depth + 1, order, comparer, a, b); } return equality } return multiPropertySorter } const getSortStrategy = (sortBy, comparer, order) => { const type = typeof sortBy // Flat array sorter if (sortBy === undefined || sortBy === true) return (a, b) => comparer(a, b, order); // Sort list of objects by single object key if (type === 'string') { throwInvalidConfigErrorIfTrue(sortBy.includes('.'), 'String syntax not allowed for nested properties.') return (a, b) => comparer(a[sortBy], b[sortBy], order) } // Sort list of objects by single function sorter if (type === 'function') return (a, b) => comparer(sortBy(a), sortBy(b), order) // Sort by multiple properties if (isArray(sortBy)) { const multiPropSorter = multiPropertySorterProvider(comparer) return (a, b) => multiPropSorter(sortBy[0], sortBy, 1, order, comparer, a, b); } // Unpack object config to get actual sorter strategy const objectSorterConfig = unpackObjectSorter(sortBy) return getSortStrategy(objectSorterConfig.sortBy, objectSorterConfig.comparer || comparer, objectSorterConfig.order) } const sortArray = (order, ctx, sortBy, comparer) => { if (!isArray(ctx)) return ctx if (isArray(sortBy) && sortBy.length < 2)[sortBy] = sortBy return ctx.sort(getSortStrategy(sortBy, comparer, order)) } const createNewSortInstance = (opts) => { const comparer = castComparer(opts.comparer) return (arrayToSort) => { const ctx = isArray(arrayToSort) && !opts.inPlaceSorting ? arrayToSort.slice() : arrayToSort; return { asc: (sortBy) => sortArray(1, ctx, sortBy, comparer), desc: (sortBy) => sortArray(-1, ctx, sortBy, comparer), by: sortBy => sortArray(1, ctx, sortBy, comparer), } } } const defaultComparer = (a, b, order) => { if (a == null) return order if (b == null) return -order if (typeof a !== typeof b) return typeof a < typeof b ? -1 : 1 if (a < b) return -1 if (a > b) return 1 return 0 } var sort = createNewSortInstance({ comparer: defaultComparer, }) var sortTS = fastSortTS() function runTests(sort) { sort([1, 4, 2]).asc() sort([1, 4, 2]).by({ asc: true }) sort([1, 4, 2]).desc() sort([1, 4, 2]).by({ desc: true }) }
Tests:
JS fast-sort
for(let i = 0; i < 10000; i++){ runTests(sort) }
TS fast-sort
for(let i = 0; i < 10000; i++){ runTests(sortTS) }