Memory leak in discord.js MessageCollector when not stopped
0 reputation · 11 Jun 2021, 17:22 UTC
0 reputation · 11 Jun 2021, 17:22 UTC
The goal is to determine whether a MessageCollector that is never stopped retains references to all collected messages, causing heap growth. In discord.js v14, collectors keep an internal Collection that is only cleared when collector.stop() is invoked. When many collectors are created for user prompts and never stopped, the process memory usage rises proportionally to the number of collected messages.
• The leak is suspected only when collector.stop() or collector.dispose() is omitted.
• It is unclear if the built‑in timeout option fully releases the cache or if a manual stop is required.
• The impact on long‑running bots that spawn thousands of collectors over time is not quantified.
collector.stop() after a successful collection guarantee that the internal Collection is garbage‑collectable, or are there still hidden references?end event automatically clear the cache, or must stop() be called explicitly?process.memoryUsage().heapUsed between a collector that is never stopped and one that is stopped in a finally block?35775 reputation · 11 Jun 2021, 19:08 UTC
In Discord.js v14 a MessageCollector keeps every message it receives in an internal Collection. That collection is only cleared when collector.stop() (or collector.dispose()) is called. The timeout option internally invokes stop() when it expires, so the end event is emitted and the cache is released automatically.
collector.stop() deletes the internal message Collection and removes all listeners, making the message objects eligible for garbage collection.timeout option triggers stop() automatically; collectors do not leak when a timeout is set.Collection retains references to every collected message, causing process.memoryUsage().heapUsed to grow roughly linearly with the number of messages.--expose-gc flag to enable manual garbage collection.const before = process.memoryUsage().heapUsed;
new MessageCollector(channel, {time: 5000})) and let it gather 100 messages.collector.stop() and measure the heap again:
const afterStop = process.memoryUsage().heapUsed;
console.log('heap after stop:', afterStop - before, 'bytes');
stop(). Measure the heap:
const afterNoStop = process.memoryUsage().heapUsed;
console.log('heap without stop:', afterNoStop - before, 'bytes');
global.gc() and observe the heap drop after stop().--inspect and take heap snapshots before and after stop() using Chrome DevTools to confirm that no message objects are referenced.If heap usage remains high after calling stop(), verify that no custom listeners are attached to the collector or to individual messages, as those can keep references alive. If you suspect such listeners, share the relevant code snippet so we can confirm whether they are the source of the leak.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.