Help ensuring best makecache and sweeper options

These are my current makeCache and sweeper settings within my client:
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
],
shards: getInfo().SHARD_LIST,
shardCount: getInfo().TOTAL_SHARDS,
makeCache: Options.cacheWithLimits({
MessageManager: 0,
GuildInviteManager: 0,
GuildEmojiManager: 0,
GuildStickerManager: 0,
GuildBanManager: 0,
GuildScheduledEventManager: 0,
ReactionUserManager: 0,
BaseGuildEmojiManager: 0,
AutoModerationRuleManager: 0,
ThreadManager: 0,
ThreadMemberManager: 0,
GuildTextThreadManager: 0,
GuildForumThreadManager: 0,
GuildMemberManager: {
maxSize: 30,
keepOverLimit: member => member.id === member.client.user.id
}
}),
sweepers: {
...Options.DefaultSweeperSettings,
users: {
interval: 3600, // Every hour...
filter: () => (user: User) => user.id !== user.client.user.id // Remove all users except for bot.
}
}
}) as Client & { cluster: ClusterClient<Client> };
const client = new Client({
intents: [
GatewayIntentBits.Guilds,
GatewayIntentBits.GuildVoiceStates,
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent
],
shards: getInfo().SHARD_LIST,
shardCount: getInfo().TOTAL_SHARDS,
makeCache: Options.cacheWithLimits({
MessageManager: 0,
GuildInviteManager: 0,
GuildEmojiManager: 0,
GuildStickerManager: 0,
GuildBanManager: 0,
GuildScheduledEventManager: 0,
ReactionUserManager: 0,
BaseGuildEmojiManager: 0,
AutoModerationRuleManager: 0,
ThreadManager: 0,
ThreadMemberManager: 0,
GuildTextThreadManager: 0,
GuildForumThreadManager: 0,
GuildMemberManager: {
maxSize: 30,
keepOverLimit: member => member.id === member.client.user.id
}
}),
sweepers: {
...Options.DefaultSweeperSettings,
users: {
interval: 3600, // Every hour...
filter: () => (user: User) => user.id !== user.client.user.id // Remove all users except for bot.
}
}
}) as Client & { cluster: ClusterClient<Client> };
My current issue is that, even with these settings, my bot ends up accumulating a lot of RAM over time (it gets up to 10.5gb at which point, I automatically restart it to ensure server doesn't crash). My bot is in 67k servers and is primarily a voice bot that responds to slash commands and has features that read text messages too. My main hypothesis at the moment is that I am missing a cache/sweeper related setting that is causing many things to be cached when it doesn't need to be, thus causing the increase in RAM over time. Any help is greatly appreciated, and feel free to ask me other questions that can help inform other parameter changes.
10 Replies
d.js toolkit
d.js toolkitโ€ข3w ago
- What's your exact discord.js npm list discord.js and node node -v version? - Not a discord.js issue? Check out #other-js-ts. - Consider reading #how-to-get-help to improve your question! - Explain what exactly your issue is. - Post the full error stack trace, not just the top part! - Show your code! - Issue solved? Press the button!
dzlandis
dzlandisOPโ€ข3w ago
When I list the processes by running htop (or regular top) it shows different instances of the bot.js file as using the most memory, which I think is to be expected because that is the file that is loaded by the main cluster manager for each cluster. I do have a heap dump from a while ago at this point, but I was never really able to understand the information from it (and I'm not sure if it's still accurate since it's been like almost 2 years now since I did that). I could take another one if you think that's a good avenue to try, but given I wasn't able to gain much from the information last time, I'm a little skeptical. Happy to share the information of the previous one if helpful as a starting point. And as for the recording/playing in voice channels not being freed, again I'm not really sure where to start. I use @discordjs/voice for all that stuff, so I assume the bulk of it is just managed internally by that. I do create a new audio resource each time the user runs one of the commands, but I've always just assumed that JS's garbage collection would clean up the data in the variable at the end of the command file when there are no longer any references to the audio Readable variable. ๐Ÿคทโ€โ™‚๏ธ
dzlandis
dzlandisOPโ€ข3w ago
One thing I have noticed that is pretty strange, is I get a lot of these small FFMPEG processes that could be contributing to the issue. In terms of resources, each one uses like 0.1% of memory usage (which I suppose can accumulate with enough processes), and as far as I can tell no CPU usage. May also explain why there were no red flags in the heapdump, as it's a separate process that was likely left unexpected. They seem to be like weird dead static processes? I've looked into it a few time, they always seem to reappear so I've just assumed it's intended behavior of the ffmpeg-static package.
No description
dzlandis
dzlandisOPโ€ข3w ago
The ffmpeg issue has to be a problem with @discordjs/voice then, because I do no manual things with ffmpeg-static except for this one case with prism-media (which is what @discordjs/voice uses internally I believe anyway):
const transcoder = new FFmpeg({
args: ['-i', 'pipe:0', '-f', 'mp3']
}) as any;

const rawAudio = pipeline(readable, transcoder, bufferStream, err => {
if (err) logger.error(config({ name: 'pipeline' }), err);
});

for await (const chunk of rawAudio) {
buffers.push(chunk);
}
rawAudio.destroy();
transcoder.destroy();
const transcoder = new FFmpeg({
args: ['-i', 'pipe:0', '-f', 'mp3']
}) as any;

const rawAudio = pipeline(readable, transcoder, bufferStream, err => {
if (err) logger.error(config({ name: 'pipeline' }), err);
});

for await (const chunk of rawAudio) {
buffers.push(chunk);
}
rawAudio.destroy();
transcoder.destroy();
But even here, I destroy the streams so it should theoretically be fine? And the pipe here is pipe:0 whereas in the image I previously attached it is pipe:1 unless there is some weird discrepancy relating to the pipe number for some reason. ๐Ÿคทโ€โ™‚๏ธ And also just realizing, this part is mp3 whereas the other screenshot mentions opus Ah ffmpeg-static is outdated, wasn't aware of that. What should I be using instead though? Windows in dev, linux in prod
dzlandis
dzlandisOPโ€ข3w ago
I always just used ffmpeg-static because that's what the guide said and I thought it would be the easiest across platforms https://discordjs.guide/voice/#installation
discord.js Guide
Imagine a guide... that explores the many possibilities for your discord.js bot.
No description
dzlandis
dzlandisOPโ€ข3w ago
Well interestingly enough, my windows version was using a native install of ffmpeg which I just updated, how about that ๐Ÿ‘€ And as for on the Linux prod, the only version it has is ffmpeg-static I'll give that a try and see if it makes a difference ๐Ÿ‘ So some updates: - The ffmpeg from ffmpeg-static was version 6.0 (newest available version is 7.1) - The newest ffmpeg able to be downloaded natively on Linux on the version of Linux I am running is actually an older version (4.2.7) - Supposedly newer versions of ffmpeg are not supported on my current version of Linux (which perhaps was causing the issue with ffmpeg?) - Will probably update Linux version at some point to download the newest one, but for now, seeing if the native Linux one makes any difference ๐Ÿคทโ€โ™‚๏ธ @Qjuh same issue unfortunately, starting to see some ffmpeg dead process behavior despite using native to system ffmpeg as opposed to ffmpeg-static
dzlandis
dzlandisOPโ€ข3w ago
No description
dzlandis
dzlandisOPโ€ข3w ago
GitHub
Audio resource write after end error cause memory leak ยท Issue #896...
Which package is this bug report for? voice Issue description 1.Play a song using ytdl=>ffmpeg=>audio resource 2.try to get a write after end error 3.ffmpeg process won't shut, ytdl and f...
dzlandis
dzlandisOPโ€ข3w ago
Nope, not using ytdl at all They are streams from elsewhere More specifically, it's a ReadableStream As in, do the opus encoding manually with prism-media and then make that the audio resource? I'll give it a try Welp, I tried following similar steps and wasn't able to get it working :( opus encoding part gave me a generic error
Aus_Karlos
Aus_Karlosโ€ข3w ago
When your using ReadStream from the external source are you handling closing the stream? Sometimes piping a stream to something like ffmpeg doesn't always get handled correctly. I have transcoding server using native ffmpeg which is spawn from a pool of workers (Job with source path -> WorkerPool -> fmpeg (fluent-ffmpeg wrapper) -> 4x threads spawn). When my worker gets a job it reads the file into a stream and ffmpeg does its thing. I've noticed that in some circumstances the stream wont close after ffmpqg has done its thing and I need o make sure i call destroy() on the stream. Its usually Linux that has the memory leak, Windows seems to close the stream properly.

Did you find this page helpful?