Toggle navigation
MeasureThat.net
Create a benchmark
Tools
Feedback
FAQ
Register
Log In
Run results for:
deepFreeze (Object.freeze)
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze#deep_freezing
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/142.0.0.0 Mobile Safari/537.36 EdgA/142.0.0.0
Browser:
Chrome Mobile 142
Operating system:
Android
Device Platform:
Mobile
Date tested:
5 months ago
Test name
Executions per second
Stack + WeakSet Cycle Detection
3077460.0 Ops/sec
Recursively Freeze
1250388.8 Ops/sec
Copy-on-write
23450162.0 Ops/sec
Script Preparation code:
function deepFreeze(obj) { const stack = [obj]; const visited = new WeakSet(); while (stack.length > 0) { const current = stack.pop(); if (visited.has(current)) continue; visited.add(current); Object.freeze(current); for (const key of Reflect.ownKeys(current)) { const value = current[key]; if ( value !== null && (typeof value === "object" || typeof value === "function") && !Object.isFrozen(value) ) { stack.push(value); } } } return obj; } function deepFreeze2(object) { // Retrieve the property names defined on object const propNames = Reflect.ownKeys(object); // Freeze properties before freezing self for (const name of propNames) { const value = object[name]; if ((value && typeof value === "object") || typeof value === "function") { deepFreeze(value); } } return Object.freeze(object); } function cowFreeze(obj) { return new Proxy(obj, { set(target, prop, value) { throw new Error("Immutable: cannot modify frozen object"); }, get(target, prop) { const val = target[prop]; if (val && typeof val === "object") { return cowFreeze(val); // lazily wrap nested objects } return val; } }); } // Large fake object manufacturer function createMockData({ depth = 4, breadth = 6, includeCycles = true, crossLinkRatio = 0.02 } = {}) { // nodes list to optionally create cross-links const nodes = []; function makeNode(level, path) { const node = { __id: path.join('.') }; nodes.push(node); // add many primitive props to increase size for (let i = 0; i < Math.min(8, breadth); i++) { node['p' + i] = `val-${path.join('-')}-${i}`; } // add symbol keys occasionally if (level % 2 === 0) { const s = Symbol('sym' + path.join('-')); node[s] = `symval-${path.join('-')}`; } if (level < depth) { node.children = []; for (let b = 0; b < breadth; b++) { const child = makeNode(level + 1, path.concat(b)); node.children.push(child); } } else { // leaf: add a large array to increase memory footprint node.leafArray = new Array(Math.min(200, breadth * 20)).fill(0).map((_, i) => `${path.join('-')}-item-${i}`); } return node; } const root = makeNode(0, ['root']); if (includeCycles) { // add some self-loops and cross-links for (let i = 0; i < Math.max(1, Math.floor(nodes.length * 0.005)); i++) { const idx = Math.floor(Math.random() * nodes.length); nodes[idx].self = nodes[idx]; // self-loop } // cross links based on ratio const crossCount = Math.floor(nodes.length * crossLinkRatio); for (let i = 0; i < crossCount; i++) { const a = nodes[Math.floor(Math.random() * nodes.length)]; const b = nodes[Math.floor(Math.random() * nodes.length)]; if (a && b && a !== b) { // attach a cross reference (a.crossRefs || (a.crossRefs = [])).push(b); } } // optional parent references using WeakMap style external map // (not attached to objects to avoid extra cycles unless desired) } return { root, _meta: { createdAt: Date.now(), nodeCount: nodes.length } }; } const small = createMockData({ depth: 1, breadth: 2, includeCycles: false }); const big = createMockData(({ depth: 2, breadth: 3, includeCycles: true, crossLinkRatio: 0.005 }));
Tests:
(Small Object) Stack + WeakSet Cycle Detection
deepFreeze(structuredClone(small));
(Small Object) Recursively Freeze
deepFreeze2(structuredClone(small));
(Small Object) Copy-on-write
cowFreeze(structuredClone(small));
(Big Object) Stack + WeakSet Cycle Detection
deepFreeze(structuredClone(big));
(Big Object) Recursively Freeze
deepFreeze2(structuredClone(big));
(Big Object) Proxy copy-on-write
cowFreeze(structuredClone(big));