Last active
February 18, 2023 12:53
-
-
Save shalvah/e50345ef0e1a7ef4ede974d84bf362d3 to your computer and use it in GitHub Desktop.
Testing garbage collection of circular references in PHP and JS. Thread: https://twitter.com/theshalvah/status/1308797556827267075
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Make sure to run with node --expose-gc | |
// Control script for the circular references test | |
// We set circular references, but we remove them explicitly before removing the parent object | |
// On my machine, memory usage increases by around +1kB at first, then "stabilises" and increases more slowly | |
(async () => { | |
while(1) { | |
let a = {}; | |
let b = {}; | |
a.f = b; | |
b.f = a; | |
let mem = process.memoryUsage(); | |
console.log("Total used memory: " + new Intl.NumberFormat().format(mem.heapUsed) + " bytes"); | |
console.log("Total allocated memory: " + new Intl.NumberFormat().format(mem.heapTotal) + " bytes"); | |
// console.log("Total used memory: " + new Intl.NumberFormat().format(window.performance.memory.usedJSHeapSize) + " bytes"); | |
// console.log("Total allocated memory: " + new Intl.NumberFormat().format(window.performance.memory.totalJSHeapSize) + " bytes"); | |
await new Promise((res) => setTimeout(res, 1000)); // Sleep for 1s | |
delete a.f; | |
delete b.f; | |
delete a; | |
delete b; | |
gc(); | |
} | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Control script for the circular references test | |
// We set circular references, but we remove them explicitly before removing the parent object | |
// In my tests, memory usage increases for a bit at first (by around 90B), | |
// then "stabilises" after a few seconds and increases only slowly. | |
while(1) { | |
$a = new \stdClass; | |
$b = new \stdClass; | |
$a->f = $b; | |
$b->f = $a; | |
print "Total used memory: " . number_format(memory_get_usage()) . " bytes\n"; | |
print "Total allocated memory: " . number_format(memory_get_usage(true)) . " bytes\n"; | |
sleep(1); | |
unset($a->f); | |
unset($b->f); | |
unset($a); | |
unset($b); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Make sure to run with node --expose-gc | |
// Test script for the circular references test | |
// Set circular references, and remove the parent objects without removing the references to each other | |
// On my machine, memory usage increases by around +1kB at first, then "stabilises" and increases more slowly | |
(async () => { | |
while(1) { | |
let a = {}; | |
let b = {}; | |
a.f = b; | |
b.f = a; | |
let mem = process.memoryUsage(); | |
console.log("Total used memory: " + new Intl.NumberFormat().format(mem.heapUsed) + " bytes"); | |
console.log("Total allocated memory: " + new Intl.NumberFormat().format(mem.heapTotal) + " bytes"); | |
// console.log("Total used memory: " + new Intl.NumberFormat().format(window.performance.memory.usedJSHeapSize) + " bytes"); | |
// console.log("Total allocated memory: " + new Intl.NumberFormat().format(window.performance.memory.totalJSHeapSize) + " bytes"); | |
await new Promise((res) => setTimeout(res, 1000)); // Sleep for 1s | |
delete a; | |
delete b; | |
gc(); | |
} | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Test script to see whether PHP properly GCs circular references | |
// Set circular references, and remove the parent objects without removing the references to each other | |
// Memory usage increases dramatically. On my machine, it's around +1kB each time. | |
while(1) { | |
$a = new \stdClass; | |
$b = new \stdClass; | |
$a->f = $b; | |
$b->f = $a; | |
print "Total used memory: " . number_format(memory_get_usage()) . " bytes\n"; | |
print "Total allocated memory: " . number_format(memory_get_usage(true)) . " bytes\n"; | |
sleep(1); | |
unset($a); | |
unset($b); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Make sure to run with node --expose-gc | |
// Control script for the circular references (memory island) test | |
// We set circular references, but we remove them explicitly before removing the parent object | |
// On my machine, memory usage increases by around +1kB at first, then "stabilises" and increases more slowly | |
function marry(man, woman) { | |
woman.husband = man; | |
man.wife = woman; | |
return { | |
father: man, | |
mother: woman | |
} | |
} | |
(async () => { | |
while (1) { | |
let family = marry({}, {}); | |
let mem = process.memoryUsage(); | |
console.log("Total used memory: " + new Intl.NumberFormat().format(mem.heapUsed) + " bytes"); | |
console.log("Total allocated memory: " + new Intl.NumberFormat().format(mem.heapTotal) + " bytes"); | |
// console.log("Total used memory: " + new Intl.NumberFormat().format(window.performance.memory.usedJSHeapSize) + " bytes"); | |
// console.log("Total allocated memory: " + new Intl.NumberFormat().format(window.performance.memory.totalJSHeapSize) + " bytes"); | |
await new Promise((res) => setTimeout(res, 1000)); // Sleep for 1s | |
delete family.father.wife; | |
delete family.mother.husband; | |
delete family.mother; | |
delete family.father; | |
delete family; | |
gc(); | |
} | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Control script for the circular references (memory island) test | |
// We set circular references, but we remove them explicitly before removing the parent object | |
// In my tests, memory usage increases for a bit at first (by around 70B), | |
// then "stabilises" after a few seconds and increases only slowly. | |
function marry($man, $woman) { | |
$woman->husband = $man; | |
$man->wife = $woman; | |
$result = new \stdClass; | |
$result->father = $man; | |
$result->mother = $woman; | |
return $result; | |
} | |
while(1) { | |
$family = marry(new \stdClass, new \stdClass); | |
print "Total used memory: " . number_format(memory_get_usage()) . " bytes\n"; | |
print "Total allocated memory: " . number_format(memory_get_usage(true)) . " bytes\n"; | |
unset($family->father->wife); | |
unset($family->mother->husband); | |
unset($family->mother); | |
unset($family->father); | |
unset($family); | |
sleep(1); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Make sure to run with node --expose-gc | |
// Test script for the circular references (memory island) test | |
// Set circular references, and remove the parent objects without removing the references to each other | |
// On my machine, memory usage increases by around +1kB at first, then "stabilises" and increases more slowly | |
function marry(man, woman) { | |
woman.husband = man; | |
man.wife = woman; | |
return { | |
father: man, | |
mother: woman | |
} | |
} | |
(async () => { | |
while (1) { | |
let family = marry({}, {}); | |
let mem = process.memoryUsage(); | |
console.log("Total used memory: " + new Intl.NumberFormat().format(mem.heapUsed) + " bytes"); | |
console.log("Total allocated memory: " + new Intl.NumberFormat().format(mem.heapTotal) + " bytes"); | |
// console.log("Total used memory: " + new Intl.NumberFormat().format(window.performance.memory.usedJSHeapSize) + " bytes"); | |
// console.log("Total allocated memory: " + new Intl.NumberFormat().format(window.performance.memory.totalJSHeapSize) + " bytes"); | |
await new Promise((res) => setTimeout(res, 1000)); // Sleep for 1s | |
delete family; | |
gc(); | |
} | |
})(); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Test script for the circular references (memory island) test | |
// Unset the parent reference without getting rid of the child circular references, leading to an unreachable "memory island" | |
// Memory usage increases dramatically. On my machine, it's around +800B each time. | |
function marry($man, $woman) { | |
$woman->husband = $man; | |
$man->wife = $woman; | |
$result = new \stdClass; | |
$result->father = $man; | |
$result->mother = $woman; | |
return $result; | |
} | |
while(1) { | |
$family = marry(new \stdClass, new \stdClass); | |
print "Total used memory: " . number_format(memory_get_usage()) . " bytes\n"; | |
print "Total allocated memory: " . number_format(memory_get_usage(true)) . " bytes\n"; | |
unset($family); | |
sleep(1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment