Skip to content

Instantly share code, notes, and snippets.

@Hypercubed
Last active September 19, 2016 14:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hypercubed/d6bacd4ce0d5835b801ba028f9b1c81b to your computer and use it in GitHub Desktop.
Save Hypercubed/d6bacd4ce0d5835b801ba028f9b1c81b to your computer and use it in GitHub Desktop.
node_modules
{
"name": "clone-speed-tests",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "cross-env NODE_ENV=production node run.js | tee results.md"
},
"keywords": [],
"author": "J. Harshbarger",
"license": "MIT",
"dependencies": {
"babyparse": "^0.4.6",
"chuhai": "^1.2.0",
"cross-env": "^2.0.1",
"isomorphic-fetch": "^2.2.1",
"lodash": "^4.15.0",
"microtime": "^2.1.1",
"platform": "^1.3.1"
},
"xo": {
"semicolon": true,
"esnext": true,
"space": 2,
"plugins": []
},
"devDependencies": {
"xo": "^0.16.0"
},
"repository": {
"type": "git",
"url": "git+ssh://git@gist.github.com/d6bacd4ce0d5835b801ba028f9b1c81b.git"
},
"bugs": {
"url": "https://gist.github.com/d6bacd4ce0d5835b801ba028f9b1c81b"
},
"homepage": "https://gist.github.com/d6bacd4ce0d5835b801ba028f9b1c81b",
"description": ""
}

Node.js 6.3.1 on Darwin 64-bit

clone

.map + Object.assign Polyfill (without checks) x 759 ops/sec ±4.79% (11 runs sampled)
.map + Object.assign Polyfill x 720 ops/sec ±7.29% (11 runs sampled)
.map + Object.assign x 474 ops/sec ±4.80% (11 runs sampled)
.map + lodash.assign x 300 ops/sec ±6.55% (11 runs sampled)
.map + lodash.clone x 227 ops/sec ±7.44% (11 runs sampled)
JSON string/parse x 219 ops/sec ±10.27% (10 runs sampled)
lodash.cloneDeep x 146 ops/sec ±14.54% (11 runs sampled)

Fastest is .map + Object.assign Polyfill (without checks), .map + Object.assign Polyfill

const assert = require('assert');
const lodash = require('lodash');
const suite = require('chuhai');
const Baby = require('babyparse');
const platform = require('platform');
const fetch = require('isomorphic-fetch');
/* const gz = fs.readFileSync('h1bs.csv.gz');
const text = zlib.gunzipSync(gz);
const data = Baby.parse(String(text), {
header: true,
delimiter: ',',
skipEmptyLines: true
}).data.slice(0, 5000); */
console.log(`# ${platform.description}\n`);
suite.cb('clone', s => {
s.set('maxTime', 0.1);
s.set('minSamples', 10);
let copy = null;
let data = null;
s.cycle(() => {
assert(copy !== null);
assert(copy !== data);
assert(copy[0] !== data[0]);
assert.deepStrictEqual(copy, data);
copy = null;
});
s.bench('lodash.cloneDeep', () => {
copy = lodash.cloneDeep(data);
});
s.bench('.map + lodash.clone', () => {
copy = data.map(d => lodash.clone(d));
});
s.bench('.map + lodash.assign', () => {
copy = data.map(d => lodash.assign({}, d));
});
s.bench('JSON string/parse', () => {
copy = JSON.parse(JSON.stringify(data));
});
s.bench('.map + Object.assign', () => {
copy = data.map(d => Object.assign({}, d));
});
s.bench('.map + Object.assign Polyfill', () => {
copy = data.map(d => objectAssignPolyfill({}, d));
});
s.bench('.map + Object.assign Polyfill (without checks)', () => {
copy = data.map(d => objectAssignPolyfillYOLO({}, d));
});
return fetch('http://swizec.github.io/h1b-software-salaries/data/h1bs.csv')
.then(response => {
if (response.status >= 400) {
throw new Error('Bad response from server');
}
return response.text();
})
.then(text => {
data = Baby.parse(text, {
header: true,
delimiter: ',',
skipEmptyLines: true
}).data.slice(0, 1000);
s.run();
});
});
// from https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
function objectAssignPolyfill(target) {
'use strict';
// We must check against these specific cases.
if (target === undefined || target === null) {
throw new TypeError('Cannot convert undefined or null to object');
}
const output = Object(target);
for (let index = 1; index < arguments.length; index++) {
const source = arguments[index];
if (source !== undefined && source !== null) {
for (const nextKey in source) {
if (Object.prototype.hasOwnProperty.call(source, nextKey)) {
output[nextKey] = source[nextKey];
}
}
}
}
return output;
}
function objectAssignPolyfillYOLO(output, source) {
for (const nextKey in source) {
if (Object.prototype.hasOwnProperty.call(source, nextKey)) {
output[nextKey] = source[nextKey];
}
}
return output;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment