-
-
Save wolever/d95c7143af5789161868c97a0ce9e2fe to your computer and use it in GitHub Desktop.
Revisions
-
wolever revised this gist
Mar 6, 2019 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,6 @@ #!/usr/bin/env node // My modifications to this code are public domain const { writeSync, readFile } = require("fs") const async_hooks = require("async_hooks") -
wolever revised this gist
Mar 6, 2019 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,7 @@ #!/usr/bin/env node # This code is public domain. const { writeSync, readFile } = require("fs") const async_hooks = require("async_hooks") -
wolever revised this gist
Mar 6, 2019 . 1 changed file with 74 additions and 22 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,37 +1,102 @@ #!/usr/bin/env node const { writeSync, readFile } = require("fs") const async_hooks = require("async_hooks") function showStack() { let e = new Error() writeSync(1, e.stack.split('\n').slice(2).join('\n') + '\n') } const ignoreEventIds = new Set() // For this example, only track timer (ex, setTimeout) and FS (ex, readFile) // events. const eventsToTrack = [ 'Timer.emitInitNative', 'FSReqWrap.emitInitNative', ] async function printLeakedEvents(f) { // Track all active event IDs const eventIDs = new Set() // Set up an async hook to increment and decrement the counter const asyncHook = async_hooks.createHook({ init: (asyncID) => { writeSync(1, `init: ${asyncID}\n`) showStack() const stack = (new Error()).stack const shouldTrack = eventsToTrack.filter(e => stack.indexOf(e) >= 0).length > 0 ;(shouldTrack ? eventIDs : ignoreEventIds).add(asyncID) }, before: (asyncID) => { writeSync(1, `before: ${asyncID}\n`) showStack() }, after: (asyncID) => { writeSync(1, `after: ${asyncID}\n`) showStack() eventIDs.delete(asyncID) }, destroy: (asyncID) => { writeSync(1, `destroy: ${asyncID}\n`) showStack() }, }); // run the function with the async hook enabled writeSync(1, `\n\n+++ start\n`) asyncHook.enable() let x = f() writeSync(1, `await:\n`) try { await x } finally { asyncHook.disable() writeSync(1, `--- finally\n`) } // print the number of hooks (using writeSync to be 100% sure that we don't // create any new events) writeSync(1, `leaked: ${Array.from(eventIDs).join(', ')}\n`) } async function main() { // do no async stuff await printLeakedEvents(() => 0) await printLeakedEvents(() => { writeSync(1, `Leaky vvv\n`) setTimeout(() => {}, 100) writeSync(1, `Leaky ^^^\n`) let x writeSync(1, `NOT leaky vvv\n`) let res = new Promise(res => x = res) writeSync(1, `NOT leaky ^^^\n`) writeSync(1, `timeout vvv\n`) setTimeout(x, 10) writeSync(1, `timeout ^^^\n`) writeSync(1, `.then vvv\n`) res = res.then(() => { return new Promise(res => { writeSync(1, `.readFile vvv\n`) readFile(__filename, res) writeSync(1, `.readFile ^^^\n`) }) }) writeSync(1, `.then ^^^\n`) return res }) await new Promise(res => setTimeout(res, 100)) console.log('Done!') /* // do no async stuff await printLeakedEvents(async () => 0) @@ -48,25 +113,12 @@ async function main() { await printLeakedEvents(async () => { // unresolved promise await new Promise(function(resolve, reject) { setTimeout(resolve, 100); }).then(() => { // do nothing, but we do want a "then" }) }) */ } main() -
garybernhardt revised this gist
Mar 4, 2019 . 1 changed file with 27 additions and 10 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -10,7 +10,7 @@ async function printLeakedEvents(f) { // Set up an async hook to increment and decrement the counter const asyncHook = async_hooks.createHook({ init: (asyncID) => { eventIDs.add(asyncID) }, after: (asyncID) => { @@ -32,24 +32,41 @@ async function printLeakedEvents(f) { } async function main() { // do no async stuff await printLeakedEvents(async () => 0) // do no async stuff again to make sure it's reliable await printLeakedEvents(async () => 0) // leak a promise await printLeakedEvents(async () => { // unresolved promise new Promise(function(resolve, reject) { setTimeout(resolve, 1000); }) }) // create a promise and resolve it correctly, including `then` and `await` await printLeakedEvents(async () => { // unresolved promise await new Promise(function(resolve, reject) { setTimeout(resolve, 1000); }).then(() => { // do nothing, but we do want a "then" }) }) } main() // Output: // 6 // 6 // 8 // 8 // The questions: // // 1. Why are 6 events created ("init"ed) but not resolved when I call a // synchronous function? // // 2. Why do I see a net event change of 8 regardless of whether I correctly // `await` the promise with a `then`, vs. simply leaking it? -
garybernhardt revised this gist
Mar 4, 2019 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -36,7 +36,7 @@ async function main() { await printLeakedEvents(async () => 0) await printLeakedEvents(async () => { // unresolved promise new Promise(function(resolve, reject) { setTimeout(resolve, 1000); }) }) } -
garybernhardt revised this gist
Mar 4, 2019 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -28,7 +28,7 @@ async function printLeakedEvents(f) { // print the number of hooks (using writeSync to be 100% sure that we don't // create any new events) writeSync(1, eventIDs.size + "\n") } async function main() { -
garybernhardt revised this gist
Mar 4, 2019 . 1 changed file with 24 additions and 8 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -1,14 +1,21 @@ // This has been updated. You'll have to go back in time in the gist history to // see older versions. const { writeSync } = require("fs") const async_hooks = require("async_hooks") async function printLeakedEvents(f) { // Track all active event IDs const eventIDs = new Set() // Set up an async hook to increment and decrement the counter const asyncHook = async_hooks.createHook({ before: (asyncID) => { eventIDs.add(asyncID) }, after: (asyncID) => { eventIDs.delete(asyncID) }, }); // run the function with the async hook enabled @@ -21,19 +28,28 @@ async function printLeakedEvents(f) { // print the number of hooks (using writeSync to be 100% sure that we don't // create any new events) writeSync(1, hookIDs.size + "\n") } async function main() { await printLeakedEvents(async () => 0) await printLeakedEvents(async () => 0) await printLeakedEvents(async () => { // unresolved promise new Promise(function(resolve, reject) { resolve(); }) }) } main() // Output: // 1 // 1 // 1 // The question: Why doesn't the unresolved promise cause more leaked events // than the `() => 0` function? // The old question (fixed in this version): why does the function `() => 0` // seem to create one event the first time it's called, but zero events the // second time? -
garybernhardt revised this gist
Mar 4, 2019 . 1 changed file with 2 additions and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -35,4 +35,5 @@ main() // 1 // 0 // The question: why does the function `() => 0` seem to create one event the // first time it's called, but zero events the second time? -
garybernhardt revised this gist
Mar 4, 2019 . 1 changed file with 7 additions and 1 deletion.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -29,4 +29,10 @@ async function main() { await printLeakedEvents(async () => 0) } main() // Output: // 1 // 0 // The question: why does the function `() => 0` seem to create one event the first time it's called, but zero events the second time? -
garybernhardt revised this gist
Mar 4, 2019 . 1 changed file with 7 additions and 5 deletions.There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -2,24 +2,26 @@ const { writeSync } = require("fs") const async_hooks = require("async_hooks") async function printLeakedEvents(f) { // Counter for the number of active hooks at any given time let activeHookCount = 0 // Set up an async hook to increment and decrement the counter const asyncHook = async_hooks.createHook({ before: () => { activeHookCount += 1 }, after: () => { activeHookCount -= 1 }, }); // run the function with the async hook enabled asyncHook.enable() try { await f() } finally { asyncHook.disable() } // print the number of hooks (using writeSync to be 100% sure that we don't // create any new events) writeSync(1, activeHookCount + "\n") } async function main() { -
garybernhardt created this gist
Mar 4, 2019 .There are no files selected for viewing
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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,30 @@ const { writeSync } = require("fs") const async_hooks = require("async_hooks") async function printLeakedEvents(f) { let activeHookCount = 0 const asyncHook = async_hooks.createHook({ before: () => { activeHookCount += 1 }, after: () => { activeHookCount -= 1 }, }); asyncHook.enable() let result try { result = await f() } finally { asyncHook.disable() } writeSync(1, activeHookCount + "\n") return result } async function main() { await printLeakedEvents(async () => 0) await printLeakedEvents(async () => 0) } main()