| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 7552de6 commit 1586c11
1 file changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,70 @@ | |||
| 1 | + 'use strict'; | ||
| 2 | + | ||
| 3 | + // TODO(joyeecheung): merge ongc.js and gcUntil from common/index.js | ||
| 4 | + // into this. | ||
| 5 | + | ||
| 6 | + // This function can be used to check if an object factor leaks or not, | ||
| 7 | + // but it needs to be used with care: | ||
| 8 | + // 1. The test should be set up with an ideally small | ||
| 9 | + // --max-old-space-size or --max-heap-size, which combined with | ||
| 10 | + // the maxCount parameter can reproduce a leak of the objects | ||
| 11 | + // created by fn(). | ||
| 12 | + // 2. This works under the assumption that if *none* of the objects | ||
| 13 | + // created by fn() can be garbage-collected, the test would crash due | ||
| 14 | + // to OOM. | ||
| 15 | + // 3. If *any* of the objects created by fn() can be garbage-collected, | ||
| 16 | + // it is considered leak-free. The FinalizationRegistry is used to | ||
| 17 | + // terminate the test early once we detect any of the object is | ||
| 18 | + // garbage-collected to make the test less prone to false positives. | ||
| 19 | + // This may be especially important for memory management relying on | ||
| 20 | + // emphemeron GC which can be inefficient to deal with extremely fast | ||
| 21 | + // heap growth. | ||
| 22 | + // Note that this can still produce false positives. When the test using | ||
| 23 | + // this function still crashes due to OOM, inspect the heap to confirm | ||
| 24 | + // if a leak is present (e.g. using heap snapshots). | ||
| 25 | + // The generateSnapshotAt parameter can be used to specify a count | ||
| 26 | + // interval to create the heap snapshot which may enforce a more thorough GC. | ||
| 27 | + // This can be tried for code paths that require it for the GC to catch up | ||
| 28 | + // with heap growth. However this type of forced GC can be in conflict with | ||
| 29 | + // other logic in V8 such as bytecode aging, and it can slow down the test | ||
| 30 | + // significantly, so it should be used scarcely and only as a last resort. | ||
| 31 | + async function checkIfCollectable( | ||
| 32 | + fn, maxCount = 4096, generateSnapshotAt = Infinity, logEvery = 128) { | ||
| 33 | + let anyFinalized = false; | ||
| 34 | + let count = 0; | ||
| 35 | + | ||
| 36 | + const f = new FinalizationRegistry(() => { | ||
| 37 | + anyFinalized = true; | ||
| 38 | + }); | ||
| 39 | + | ||
| 40 | + async function createObject() { | ||
| 41 | + const obj = await fn(); | ||
| 42 | + f.register(obj); | ||
| 43 | + if (count++ < maxCount && !anyFinalized) { | ||
| 44 | + setImmediate(createObject, 1); | ||
| 45 | + } | ||
| 46 | + // This can force a more thorough GC, but can slow the test down | ||
| 47 | + // significantly in a big heap. Use it with care. | ||
| 48 | + if (count % generateSnapshotAt === 0) { | ||
| 49 | + // XXX(joyeecheung): This itself can consume a bit of JS heap memory, | ||
| 50 | + // but the other alternative writeHeapSnapshot can run into disk space | ||
| 51 | + // not enough problems in the CI & be slower depending on file system. | ||
| 52 | + // Just do this for now as long as it works and only invent some | ||
| 53 | + // internal voodoo when we absolutely have no other choice. | ||
| 54 | + require('v8').getHeapSnapshot().pause().read(); | ||
| 55 | + console.log(`Generated heap snapshot at ${count}`); | ||
| 56 | + } | ||
| 57 | + if (count % logEvery === 0) { | ||
| 58 | + console.log(`Created ${count} objects`); | ||
| 59 | + } | ||
| 60 | + if (anyFinalized) { | ||
| 61 | + console.log(`Found finalized object at ${count}, stop testing`); | ||
| 62 | + } | ||
| 63 | + } | ||
| 64 | + | ||
| 65 | + createObject(); | ||
| 66 | + } | ||
| 67 | + | ||
| 68 | + module.exports = { | ||
| 69 | + checkIfCollectable, | ||
| 70 | + }; | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments