-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
189 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const immer = require('immer'); | ||
|
||
const immerCase = { | ||
label: 'immer', | ||
setWithString: null, | ||
setWithArray: null, | ||
}; | ||
|
||
module.exports = immerCase; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const immutableAssign = require('immutable-assign'); | ||
|
||
const immutableAssignCase = { | ||
label: 'immutable-assign', | ||
setWithString: null, | ||
setWithArray: null, | ||
}; | ||
|
||
module.exports = immutableAssignCase; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const immutable = require('immutable'); | ||
|
||
const immutableCase = { | ||
label: 'immutable.js', | ||
setWithString: null, | ||
setWithArray: null, | ||
}; | ||
|
||
module.exports = immutableCase; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
const setWith = require('lodash/setWith'); | ||
const clone = require('lodash/clone'); | ||
|
||
const lodashImmutableSet = (obj, path, value) => setWith(clone(obj), path, value, clone); | ||
|
||
const lodashCase = { | ||
label: 'lodash', | ||
setWithString: lodashImmutableSet, | ||
setWithArray: lodashImmutableSet, | ||
}; | ||
|
||
module.exports = lodashCase; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const seamlessImmutable = require('seamless-immutable'); | ||
|
||
const seamlessImmutableCase = { | ||
label: 'seamless-immutable', | ||
setWithString: null, | ||
setWithArray: null, | ||
}; | ||
|
||
module.exports = seamlessImmutableCase; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
const { set } = require('tiny-immutable-set'); | ||
|
||
const tinyImmutableSetCase = { | ||
label: 'tiny-immutable-set', | ||
setWithString: set, | ||
setWithArray: set, | ||
}; | ||
|
||
module.exports = tinyImmutableSetCase; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
const { Timeline } = require('@nelsongomes/ts-timeframe'); | ||
|
||
const allLibraries = [ | ||
require('./libraries/immer'), | ||
require('./libraries/immutable'), | ||
require('./libraries/immutable-assign'), | ||
require('./libraries/lodash'), | ||
require('./libraries/seamless-immutable'), | ||
require('./libraries/tiny-immutable-set'), | ||
]; | ||
|
||
const allScenarios = [runStringScenario, runArrayScenario, runStringScenario, runArrayScenario]; | ||
|
||
const iterationsPerRun = 25000; | ||
|
||
// An object of arrays of objects, with 5 items at each level | ||
const TEST_OBJECT_BREADTH = 10; | ||
const TEST_OBJECT = {}; | ||
for (let propNum = 0; propNum < TEST_OBJECT_BREADTH; propNum++) { | ||
TEST_OBJECT[`prop${propNum}`] = []; | ||
for (let indexNum = 0; indexNum < TEST_OBJECT_BREADTH; indexNum++) { | ||
const obj = {}; | ||
for (let deepNum = 0; deepNum < TEST_OBJECT_BREADTH; deepNum++) { | ||
obj[`deep${deepNum}`] = deepNum; | ||
} | ||
TEST_OBJECT[`prop${propNum}`].push(obj); | ||
} | ||
} | ||
|
||
////////////////////////////////// | ||
function deepFreeze(object) { | ||
// Retrieve the property names defined on object | ||
var propNames = Object.getOwnPropertyNames(object); | ||
|
||
// Freeze properties before freezing self | ||
|
||
for (let name of propNames) { | ||
let value = object[name]; | ||
|
||
if (value && typeof value === 'object') { | ||
deepFreeze(value); | ||
} | ||
} | ||
|
||
return Object.freeze(object); | ||
} | ||
deepFreeze(TEST_OBJECT); | ||
////////////////////////////////// | ||
|
||
function runStringScenario(libraryInfo) { | ||
const { label, setWithString, timeline } = libraryInfo; | ||
|
||
if (setWithString) { | ||
// Pre-generate all paths | ||
const allPaths = []; | ||
for (let i = 0; i < iterationsPerRun; i++) { | ||
const propNum = i % TEST_OBJECT_BREADTH; | ||
const indexNum = (i / TEST_OBJECT_BREADTH) % TEST_OBJECT_BREADTH; | ||
const deepNum = (i / (TEST_OBJECT_BREADTH * TEST_OBJECT_BREADTH)) % TEST_OBJECT_BREADTH; | ||
allPaths.push(`${propNum}[${indexNum}].${deepNum}`); | ||
} | ||
|
||
const event = timeline.startEvent(['string-path']); | ||
for (let i = 0; i < iterationsPerRun; i++) { | ||
setWithString(TEST_OBJECT, allPaths[i], i); | ||
} | ||
event.end(); | ||
} else { | ||
console.warn(`Library "${label}" is missing the setWithArray scenario`); | ||
} | ||
} | ||
|
||
function runArrayScenario(libraryInfo) { | ||
const { label, setWithArray, timeline } = libraryInfo; | ||
|
||
if (setWithArray) { | ||
// Pre-generate all paths | ||
const allPaths = []; | ||
for (let i = 0; i < iterationsPerRun; i++) { | ||
const prop = i % TEST_OBJECT_BREADTH; | ||
const index = (i / TEST_OBJECT_BREADTH) % TEST_OBJECT_BREADTH; | ||
const deep = (i / (TEST_OBJECT_BREADTH * TEST_OBJECT_BREADTH)) % TEST_OBJECT_BREADTH; | ||
allPaths.push([prop, index, deep]); | ||
} | ||
|
||
const event = timeline.startEvent(['array-path']); | ||
for (let i = 0; i < iterationsPerRun; i++) { | ||
setWithArray(TEST_OBJECT, allPaths[i], i); | ||
} | ||
event.end(); | ||
} else { | ||
console.warn(`Library "${label}" is missing the setWithArray scenario`); | ||
} | ||
} | ||
|
||
// We're going to run through each (library, scenario) tuple twice: | ||
// 1. For each library, run each scenario type | ||
// 2. For each scenario type, run each library | ||
|
||
for (let libNum = 0; libNum < allLibraries.length; libNum++) { | ||
allLibraries[libNum].timeline = new Timeline(); | ||
|
||
for (let scenarioNum = 0; scenarioNum < allScenarios.length; scenarioNum++) { | ||
allScenarios[scenarioNum](allLibraries[libNum]); | ||
} | ||
} | ||
|
||
for (let scenarioNum = 0; scenarioNum < allScenarios.length; scenarioNum++) { | ||
for (let libNum = 0; libNum < allLibraries.length; libNum++) { | ||
allScenarios[scenarioNum](allLibraries[libNum]); | ||
} | ||
} | ||
|
||
// Now let's take a look at the results | ||
|
||
for (let libNum = 0; libNum < allLibraries.length; libNum++) { | ||
allLibraries[libNum].timeline.end(); | ||
|
||
const { label, timeline } = allLibraries[libNum]; | ||
const [seconds, nanoseconds] = timeline.sumEventsDuration(); | ||
const totalCount = timeline.count(); | ||
const averageTime = (seconds * 1e9) / totalCount + nanoseconds / totalCount; | ||
console.log(`==== ${label} ====`); | ||
console.log( | ||
`Average time: ${seconds}.${nanoseconds}/${totalCount} = ${averageTime}ns (${averageTime / | ||
1e9}s)`, | ||
); | ||
|
||
console.log(timeline.getDuration()); | ||
console.log(timeline.generateAnalyticInfo()); | ||
} |