🤔
benchmark.jsを使用したディープコピー比較検証
JavaScriptのディープコピー方法はいくつかありますが、パフォーマンスを考えるとどれがいいのか考えものです。
そこでJavaScriptライブラリであるbenchmark.js
を使用してパフォーマンス検証していこうと思います。
検証するデータ
今回は以下のオブジェクトで検証を実施します。
const data = {
key1: 'value1',
key2: 'value2',
}
JSON.stringify()
JSON.stringify
でJSON文字列に変換し、JSON.parse
で文字列によって記述されているJavaScript の値やオブジェクトを構築します。
const deepcopy = JSON.stringify(data)
data.key1 = 'update'
console.log(data) // { key1: 'update', key2: 'value2' }
console.log(JSON.parse(deepcopy)) // { key1: 'value1', key2: 'value2' }
structuredClone()
node v17
から使用できます。
const deepcopy = structuredClone(data)
data.key1 = 'update'
console.log(data) // { key1: 'update', key2: 'value2' }
console.log(deepcopy) // { key1: 'value1', key2: 'value2' }
Lodash clonedeep()
ライブラリLodashから使用できます。
こちらはJSON.stringify()
とは違って値に制限がありません。
const clonedeep = require('lodash/cloneDeep')
const deepcopy = clonedeep(data)
data.key1 = 'update'
console.log(data) // { key1: 'update', key2: 'value2' }
console.log(deepcopy) // { key1: 'value1', key2: 'value2' }
検証結果
それぞれの検証を行なっていきます。
検証コードは以下の通りです。
functions/index.js
const clonedeep = require('lodash/cloneDeep')
const deepJson = (originData) => {
let data = null
for (let i = 0; i < 10000; i++) {
data = JSON.stringify(originData)
}
return JSON.parse(data)
}
const deepStructure = (originData) => {
let data = null
for (let i = 0; i < 10000; i++) {
data = structuredClone(originData)
}
return data
}
const deepLodash = (originData) => {
let data = null
for (let i = 0; i < 10000; i++) {
data = clonedeep(originData)
}
return data
}
module.exports = {
deepJson,
deepStructure,
deepLodash
}
main.js
const Benchmark = require('benchmark')
const { deepJson, deepStructure, deepLodash } = require('./functions')
const originData = {
key1: 'value1',
key2: 'value2',
}
const suite = new Benchmark.Suite
suite
.on('start', () => {
console.log('Test start')
})
.add('JSON', () => {
deepJson(originData)
})
.add('Structure', () => {
deepStructure(originData)
})
.add('Lodash', () => {
deepLodash(originData)
})
.on('cycle', (event) => {
console.log(String(event.target))
})
.on('complete', function () {
console.log(`Fastest is ${this.filter('fastest').map('name')}`)
})
.run({ async: true })
結果は以下のようになりました。
1秒でどれくらい実行できたかを表すops/sec
では、JSON.stringify()
を使用した方法が一番早いです。
Test start
JSON x 647 ops/sec ±0.12% (98 runs sampled)
Structure x 143 ops/sec ±0.60% (83 runs sampled)
Lodash x 479 ops/sec ±1.53% (91 runs sampled)
Fastest is JSON
最後に
一番処理が早かったJSON.stringify()
ですが、データの型に注意する必要があります。
データの型に影響を受けないようにするならばLodash clonedeep
を候補に入れてもいいかと考えます。また、対応ブラウザに気をつけてstructureClone()
を使用するのも一つの手かと思います。
Discussion