Skip to content

Instantly share code, notes, and snippets.

@wentout
Last active April 10, 2025 11:52
Show Gist options
  • Save wentout/c155aa40580da0c62a6639af89460976 to your computer and use it in GitHub Desktop.
Save wentout/c155aa40580da0c62a6639af89460976 to your computer and use it in GitHub Desktop.
Struct Sizes Comparison
'use strict';
const count = 1_000_000_000;
console.time('finished in');
const myArr = [];
let i = 0;
const handler = () => {
console.timeEnd('finished in');
console.log(`made [ ${i-1} ] elements`);
};
for (; i <= count; i++) {
const str = new String(i);
const len = str.length;
let num = 0;
const caption = str.split('').reverse().reduce((arr, value) => {
if (num > 2 && num % 3 === 0) {
arr.unshift('_');
}
num++;
arr.unshift(value);
return arr;
}, []).join('');
const item = `item : ${caption}`;
try {
myArr.push(item);
} catch (error) {
console.error(error);
handler();
process.exit();
}
if (i % 100_000 === 0) {
console.log(item);
}
}
handler();
/*
item : 56_900_000
<--- Last few GCs --->
[92570:0x12148190] 77070 ms: Mark-Compact 4056.4 (4132.8) -> 4042.1 (4134.5) MB, 2487.88 / 0.00 ms (average mu = 0.124, current mu = 0.009) allocation failure; scavenge might not succeed
[92570:0x12148190] 79301 ms: Mark-Compact 4057.9 (4134.5) -> 4043.8 (4136.0) MB, 2204.34 / 0.00 ms (average mu = 0.075, current mu = 0.012) allocation failure; scavenge might not succeed
<--- JS stacktrace --->
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----
1: 0xb8d11b node::OOMErrorHandler(char const*, v8::OOMDetails const&) [node]
2: 0xf01b70 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
3: 0xf01e57 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
4: 0x1113aa5 [node]
5: 0x1114034 v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [node]
6: 0x112af24 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::internal::GarbageCollectionReason, char const*) [node]
7: 0x112b73c v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
8: 0x1101a41 v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
9: 0x1102bd5 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
10: 0x10e0226 v8::internal::Factory::NewFillerObject(int, v8::internal::AllocationAlignment, v8::internal::AllocationType, v8::internal::AllocationOrigin) [node]
11: 0x153c086 v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [node]
12: 0x7ce451e99ef6
Aborted (core dumped)
*/
'use strict';
(function () {
const count = 1_000_000;
console.time('finished in');
const myMap = new Map();
let i = 0;
const handler = () => {
console.timeEnd('finished in');
console.log(`made [ ${i - 1} ] elements`);
};
for (; i <= count; i++) {
const str = new String(i);
const len = str.length;
let num = 0;
const caption = str.split('').reverse().reduce((arr, value) => {
if (num > 2 && num % 3 === 0) {
arr.unshift('_');
}
num++;
arr.unshift(value);
return arr;
}, []).join('');
const item = `item : ${caption}`;
try {
myMap.set(item, item);
} catch (error) {
console.error(error);
handler();
process.exit();
}
if (i % 100_000 === 0) {
console.log(item);
}
}
handler();
console.time('access time');
console.log(myMap.has('item : 1_000'));
console.timeEnd('access time'); // 0.03ms
})();
/*
item : 16_700_000
RangeError: Map maximum size exceeded
at Map.set (<anonymous>)
at Object.<anonymous> (/code/_dev_tests/StructSizes/MapDeepness.js:33:15)
at Module._compile (node:internal/modules/cjs/loader:1469:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1548:10)
at Module.load (node:internal/modules/cjs/loader:1288:32)
at Module._load (node:internal/modules/cjs/loader:1104:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:173:12)
at node:internal/main/run_main_module:28:49
finished in: 22.293s
made [ 16777215 ] elements
*/
'use strict';
const count = 1_000_000_000;
console.time('finished in');
const myObj = new Object();
let i = 0;
const handler = () => {
console.timeEnd('finished in');
console.log(`made [ ${i-1} ] elements`);
};
for (; i <= count; i++) {
const str = new String(i);
const len = str.length;
let num = 0;
const caption = str.split('').reverse().reduce((arr, value) => {
if (num > 2 && num % 3 === 0) {
arr.unshift('_');
}
num++;
arr.unshift(value);
return arr;
}, []).join('');
const item = `item : ${caption}`;
try {
myObj[item] = item;
} catch (error) {
console.error(error);
handler();
process.exit();
}
if (i % 100_000 === 0) {
console.log(item);
}
}
handler();
/*
just stopped here
item : 8_300_000
*/
'use strict';
(function () {
const count = 1_000_000_000;
console.time('finished in');
var last = {
prev: null,
item: null,
next: null
};
let i = 0;
const handler = () => {
console.timeEnd('finished in');
console.log(`made [ ${i - 1} ] elements`);
};
for (; i <= count; i++) {
const str = new String(i);
const len = str.length;
let num = 0;
const caption = str.split('').reverse().reduce((arr, value) => {
if (num > 2 && num % 3 === 0) {
arr.unshift('_');
}
num++;
arr.unshift(value);
return arr;
}, []).join('');
const item = `item : ${caption}`;
try {
const current = {
prev: last,
item: item,
next: null
};
last.next = current;
last = current;
} catch (error) {
console.error(error);
handler();
process.exit();
}
if (i % 100_000 === 0) {
console.log(item);
}
}
handler();
})();
/*
item : 37_800_000
<--- Last few GCs --->
[94039:0x40fd7240] 115606 ms: Mark-Compact 4053.8 (4140.2) -> 4039.6 (4142.0) MB, 2779.59 / 0.00 ms (average mu = 0.229, current mu = 0.011) allocation failure; scavenge might not succeed
[94039:0x40fd7240] 119225 ms: Mark-Compact 4056.7 (4143.2) -> 4042.5 (4144.7) MB, 3592.37 / 0.00 ms (average mu = 0.115, current mu = 0.007) allocation failure; scavenge might not succeed
<--- JS stacktrace --->
FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----
1: 0xb8d11b node::OOMErrorHandler(char const*, v8::OOMDetails const&) [node]
2: 0xf01b70 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
3: 0xf01e57 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
4: 0x1113aa5 [node]
5: 0x112b928 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
6: 0x1101a41 v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
7: 0x1102bd5 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
8: 0x10e0226 v8::internal::Factory::NewFillerObject(int, v8::internal::AllocationAlignment, v8::internal::AllocationType, v8::internal::AllocationOrigin) [node]
9: 0x153c086 v8::internal::Runtime_AllocateInYoungGeneration(int, unsigned long*, v8::internal::Isolate*) [node]
10: 0x7039c3ed9ef6
Aborted (core dumped)
*/
'use strict';
(function () {
const count = 1_000_000;
console.time('finished in');
const init = {
name: 'init',
prev: null,
get init() {
return init;
}
};
const ids = new Map();
const prevs = new Map();
const nexts = new Map();
var last = init;
let i = 0;
const handler = () => {
console.timeEnd('finished in');
console.log(`made [ ${i - 1} ] elements`);
};
for (; i <= count; i++) {
const str = new String(i);
const len = str.length;
let num = 0;
const caption = str.split('').reverse().reduce((arr, value) => {
if (num > 2 && num % 3 === 0) {
arr.unshift('_');
}
num++;
arr.unshift(value);
return arr;
}, []).join('');
const name = `item : ${caption}`;
try {
const props = {
prev: {
value: last,
enumerable: true,
configurable: true
},
name: {
value: name,
enumerable: true,
configurable: true
},
next: {
value: null,
enumerable: true,
configurable: true
}
};
const current = Object.create(last, props);
Object.defineProperty(current, name, {
value: current,
enumerable: true,
configurable: true
});
Object.defineProperty(current, 'self', {
value: current,
enumerable: true,
configurable: true
});
Object.defineProperty(last, 'next', {
value: current,
enumerable: true,
configurable: true
});
prevs.set(current, last);
nexts.set(last, current);
last = current;
ids.set(name, current);
} catch (error) {
console.error(error);
handler();
process.exit();
}
if (i % 100_000 === 0) {
console.log(name);
}
}
handler();
console.time('access time');
const first = last['item : 0'];
console.log('proto chain object:\n', first);
console.timeEnd('access time'); // 5s
console.log('\n\n\n');
console.time('access time map [item : 0]');
console.log('map proto object:\n', ids.get('item : 0'));
console.timeEnd('access time map [item : 0]'); // 0.3ms
console.log('\n\n\n');
console.time('access time proto');
console.log('proto object:\n', Reflect.getPrototypeOf(last));
console.timeEnd('access time proto');
console.log('\n\n\n');
console.time('access time prev');
console.log('prev object:\n', last.prev);
console.timeEnd('access time prev');
console.log('\n\n\n');
console.time('access time prevs');
const proto = prevs.get(last);
console.log('prevs object:\n', proto);
console.timeEnd('access time prevs');
console.log('\n\n\n');
console.time('access time nexts');
const pnext = nexts.get(proto);
console.log('nexts object:\n', pnext);
console.timeEnd('access time nexts');
console.log('\n\n\n');
console.time('access time first → nexts');
const first_next = nexts.get(first);
console.log('first → nexts object:\n', first_next);
console.timeEnd('access time first → nexts');
console.log('\n\n\n');
console.time('access time first → nexts → next');
const first_next_next = nexts.get(first_next);
console.log('first → nexts object:\n', first_next_next);
console.timeEnd('access time first → nexts → next');
console.log('\n\n\n');
console.time('access time first_next_next proto');
console.log('proto object:\n', Reflect.getPrototypeOf(first_next_next));
console.timeEnd('access time first_next_next proto'); // 0.2ms
console.log('\n\n\n');
console.time('access time map [item : 549_997]');
console.log('map [549_997] object:\n', ids.get('item : 549_997'));
console.timeEnd('access time map [item : 549_997]'); // 0.3ms
console.log('\n\n\n');
})();
/*
item : 8_300_000
<--- Last few GCs --->
[96963:0xd1b0240] 118344 ms: Mark-Compact 3766.1 (4128.7) -> 3749.8 (4126.0) MB, 5095.31 / 0.00 ms (average mu = 0.067, current mu = 0.015) allocation failure; scavenge might not succeed
[96963:0xd1b0240] 118445 ms: Scavenge 3770.1 (4127.0) -> 3759.3 (4127.0) MB, 18.42 / 0.00 ms (average mu = 0.067, current mu = 0.015) allocation failure;
[96963:0xd1b0240] 118544 ms: Scavenge 3773.0 (4127.0) -> 3765.1 (4129.5) MB, 37.28 / 0.00 ms (average mu = 0.067, current mu = 0.015) allocation failure;
<--- JS stacktrace --->
FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of memory
----- Native stack trace -----
1: 0xb8d11b node::OOMErrorHandler(char const*, v8::OOMDetails const&) [node]
2: 0xf01b70 v8::Utils::ReportOOMFailure(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
3: 0xf01e57 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) [node]
4: 0x1113aa5 [node]
5: 0x1114034 v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [node]
6: 0x112af24 v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::internal::GarbageCollectionReason, char const*) [node]
7: 0x112b73c v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [node]
8: 0x1101a41 v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
9: 0x1102bd5 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [node]
10: 0x10df2f6 v8::internal::Factory::AllocateRaw(int, v8::internal::AllocationType, v8::internal::AllocationAlignment) [node]
11: 0x10d0a6c v8::internal::FactoryBase<v8::internal::Factory>::AllocateRawArray(int, v8::internal::AllocationType) [node]
12: 0x10d0bd4 v8::internal::FactoryBase<v8::internal::Factory>::NewFixedArrayWithFiller(v8::internal::Handle<v8::internal::Map>, int, v8::internal::Handle<v8::internal::Oddball>, v8::internal::AllocationType) [node]
13: 0x13f3d1d v8::internal::Handle<v8::internal::NameDictionary> v8::internal::HashTable<v8::internal::NameDictionary, v8::internal::NameDictionaryShape>::New<v8::internal::Isolate>(v8::internal::Isolate*, int, v8::internal::AllocationType, v8::internal::MinimumCapacity) [node]
14: 0x13f5049 v8::internal::Handle<v8::internal::NameDictionary> v8::internal::BaseNameDictionary<v8::internal::NameDictionary, v8::internal::NameDictionaryShape>::New<v8::internal::Isolate>(v8::internal::Isolate*, int, v8::internal::AllocationType, v8::internal::MinimumCapacity) [node]
15: 0x13f50c9 v8::internal::Handle<v8::internal::NameDictionary> v8::internal::NameDictionary::New<v8::internal::Isolate>(v8::internal::Isolate*, int, v8::internal::AllocationType, v8::internal::MinimumCapacity) [node]
16: 0x1356c90 v8::internal::JSObject::MigrateToMap(v8::internal::Isolate*, v8::internal::Handle<v8::internal::JSObject>, v8::internal::Handle<v8::internal::Map>, int) [node]
17: 0x135a0bc v8::internal::JSObject::OptimizeAsPrototype(v8::internal::Handle<v8::internal::JSObject>, bool) [node]
18: 0x13c794d v8::internal::Map::GetObjectCreateMap(v8::internal::Isolate*, v8::internal::Handle<v8::internal::HeapObject>) [node]
19: 0x1348bc2 v8::internal::JSObject::ObjectCreate(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>) [node]
20: 0x154580b v8::internal::Runtime_ObjectCreate(int, unsigned long*, v8::internal::Isolate*) [node]
21: 0x70589e699ef6
Aborted (core dumped)
*/
'use strict';
(function () {
const count = 1_000_000;
console.time('finished in');
const mySet = new Set();
let i = 0;
const handler = () => {
console.timeEnd('finished in');
console.log(`made [ ${i - 1} ] elements`);
};
for (; i <= count; i++) {
const str = new String(i);
const len = str.length;
let num = 0;
const caption = str.split('').reverse().reduce((arr, value) => {
if (num > 2 && num % 3 === 0) {
arr.unshift('_');
}
num++;
arr.unshift(value);
return arr;
}, []).join('');
const item = `item : ${caption}`;
try {
mySet.add(item);
} catch (error) {
console.error(error);
handler();
process.exit();
}
if (i % 100_000 === 0) {
console.log(item);
}
}
handler();
console.time('access time');
console.log(mySet.has('item : 1_000'));
console.timeEnd('access time'); // 0.03ms
})();
'use strict';
(function () {
const count = 1_000_000_000;
console.time('finished in');
const myMap = new WeakMap();
let i = 0;
let current = {
item: null,
prev: null,
next: null
};
const handler = () => {
console.timeEnd('finished in');
console.log(`made [ ${i - 1} ] elements`);
};
for (; i <= count; i++) {
const str = new String(i);
const len = str.length;
let num = 0;
const caption = str.split('').reverse().reduce((arr, value) => {
if (num > 2 && num % 3 === 0) {
arr.unshift('_');
}
num++;
arr.unshift(value);
return arr;
}, []).join('');
const item = `item : ${caption}`;
const key = {
item,
prev: current,
next: null
};
try {
myMap.set(key, item);
current.next = key;
current = key;
} catch (error) {
console.error(error);
handler();
process.exit();
}
if (i % 100_000 === 0) {
console.log(item);
}
}
handler();
console.time('access time');
console.log(myMap.get(current));
console.timeEnd('access time'); // 0.03ms
})();
/*
finished in: 1.403s
made [ 1000000 ] elements
item : 1_000_000
access time: 0.03ms
дальше очень долго и "подвисло" тут
item : 5_500_000
*/
'use strict';
(function () {
const count = 1_000_000_000;
console.time('finished in');
const mySet = new WeakSet();
let i = 0;
let current = {
item: null,
prev: null,
next: null
};
const handler = () => {
console.timeEnd('finished in');
console.log(`made [ ${i - 1} ] elements`);
};
for (; i <= count; i++) {
const str = new String(i);
const len = str.length;
let num = 0;
const caption = str.split('').reverse().reduce((arr, value) => {
if (num > 2 && num % 3 === 0) {
arr.unshift('_');
}
num++;
arr.unshift(value);
return arr;
}, []).join('');
const item = `item : ${caption}`;
const key = {
item,
prev: current,
next: null
};
try {
mySet.add(key);
current.next = key;
current = key;
} catch (error) {
console.error(error);
handler();
process.exit();
}
if (i % 100_000 === 0) {
console.log(item);
}
}
handler();
console.time('access time');
console.log(mySet.has(current));
console.timeEnd('access time'); // 0.03ms
})();
/*
finished in: 1.092s
made [ 1000000 ] elements
true
access time: 0.385ms
дальше очень медленно и просто зависло на
item : 11_100_000
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment