Skip to content

esnext.json.parse is generating (memory-wise) heavier objects #1354

Open
@Kosta-Github

Description

When using esnext.json.parse with a reviver function the deserialized objects are heavier (memory-wise) than the ones that are generated by the non-polyfilled JSON.parse() function.

How to reproduce:

// require("core-js/actual/json/parse");

// generate a large JSON string containing an array of 1_000_000 random numbers
const data = [];
for (let i = 0; i < 1_000_000; i++) {
    data.push('' + Math.floor(Math.random() * 100));
}
const json = JSON.stringify({ results: [data] });

// trivial reviver function that does nothing
const reviver = (key, value) => value;

let lastMemUsage = process.memoryUsage();
const results = [];
while (true) {
    const currentMemUsage = process.memoryUsage();
    console.log(
        `[mem] current: ${Math.floor(currentMemUsage.heapTotal / (1024*1024))}, ` +
        `delta: ${Math.floor((currentMemUsage.heapTotal - lastMemUsage.heapTotal) / (1024*1024))}`
    );
    lastMemUsage = currentMemUsage;

    const parsed = JSON.parse(json, reviver);

    // keep a reference to the parsed objects to prevent the GC from collecting them
    results.push(parsed);
}

Let the above script run for a while and observe the memory usage and delta when using unmodified JSON.parse(), which is something like:

[mem] current: 52, delta: 0
[mem] current: 88, delta: 35
[mem] current: 89, delta: 1
[mem] current: 120, delta: 30
[mem] current: 151, delta: 30
[mem] current: 182, delta: 30
[mem] current: 213, delta: 30
[mem] current: 127, delta: -86
[mem] current: 158, delta: 30
[mem] current: 189, delta: 30
[mem] current: 220, delta: 30
[mem] current: 251, delta: 30
[mem] current: 282, delta: 30
[mem] current: 313, delta: 31
[mem] current: 344, delta: 30
[mem] current: 375, delta: 30
[mem] current: 196, delta: -179
[mem] current: 227, delta: 31
[mem] current: 258, delta: 30
[mem] current: 289, delta: 30
[mem] current: 320, delta: 30
[mem] current: 350, delta: 30
[mem] current: 381, delta: 30
[mem] current: 412, delta: 30
[mem] current: 443, delta: 30
[mem] current: 474, delta: 30
[mem] current: 505, delta: 31
[mem] current: 536, delta: 30
[mem] current: 567, delta: 30
[mem] current: 598, delta: 30
...

When uncomment the first line and using the polyfilled JSON.parse() function the output looks like this:

[mem] current: 52, delta: 0
[mem] current: 202, delta: 149
[mem] current: 236, delta: 33
[mem] current: 256, delta: 20
[mem] current: 401, delta: 145
[mem] current: 557, delta: 155
[mem] current: 447, delta: -110
[mem] current: 505, delta: 57
[mem] current: 650, delta: 145
[mem] current: 806, delta: 156
[mem] current: 962, delta: 155
[mem] current: 712, delta: -250
[mem] current: 768, delta: 56
[mem] current: 826, delta: 57
[mem] current: 947, delta: 121
[mem] current: 1103, delta: 155
[mem] current: 1259, delta: 155
[mem] current: 1415, delta: 156
[mem] current: 1571, delta: 155
[mem] current: 1727, delta: 155
[mem] current: 1137, delta: -591
[mem] current: 1194, delta: 57
[mem] current: 1251, delta: 56
[mem] current: 1308, delta: 56
[mem] current: 1395, delta: 86
[mem] current: 1552, delta: 157
[mem] current: 1708, delta: 155
[mem] current: 1863, delta: 155
[mem] current: 2019, delta: 155
[mem] current: 2176, delta: 156
[mem] current: 2332, delta: 156
...

You can see that the memory usage is up to 4-5 times larger and growing way quicker.

$ node --version

v20.15.0

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions