discordjs / discord.js

A powerful JavaScript library for interacting with the Discord API
https://discord.js.org
Apache License 2.0
25.49k stars 3.97k forks source link

Possible memory leak. #2337

Closed Wodki closed 6 years ago

Wodki commented 6 years ago

Please describe the problem you are having in as much detail as possible: I have 4 Node.js instances. The 2 of them use discord.js and the other 2 don't. In the 2 that do use it, I have noticed a memory leak. The leak is about 20-30mb/day. I initially used Redis, express, native HTTP server and SQL on those two (and one is a music bot). I removed everything except the SQL backed but it still appeared to exist. I tried using the --inspect flag and I exposed the GC (did not help me much) but I still haven't figured out where exactly it is. I did not notice anything abnormal in the heap snapshots from chrome I took aside from a few message caching (which I think its normal).

Regarding my client options everything is left to default except 3-4 events that I have disabled. I also never cache users I fetch, and when the instance starts I fetch all the members from some guilds. The bot has a user base of roughly 60-70k members which some of the guilds require the fetching. Whenever I ever fetch anything; that is a user which I don't cache, or a message I always do after a few seconds delete.

The discord.js was the last thing on my list to check, but I could not find anything else. If you need me to provide anything more specific please say so. This is just a speculation but I don't think it existed in 11.2 - (perhaps) 11.1.

Further details:

kyranet commented 6 years ago

What you call "memory leak" is just discord.js indiscriminately caching more and more users/members over time. When you init your bot, you never get the 100% of users/members downloaded, it's usually a portion of them (of online users, offline/invisible usually are uncached at startup). This issue would have been fixed with #1890 that limits them, however, that did not get merged. Therefore, for now, we'll cache absolute every single thing the API sends to us.

Wodki commented 6 years ago

So essentially you are saying that when all the guild members, become online, and all (200 if I remember correctly first messages get fetched, and emojis and what not) they process will stop allocating more ram? - mind you that I do fetch all members on the ready event. So if I let the instance for a couple of days, it will eventually have cached everything and the ram used will be stable?

kyranet commented 6 years ago

Let's say, your bot has a range of 80.000 users (all unique users from all guilds your bot is in), not all of them are online, so you may start your bot with around 15.000 users online and ~65mb RAM usage, they'll eventually connect to Discord, change their presence status to online, talk... that'll make the API send us their data, which we'll cache. So in one week without fetching users, d.js will probably have 60.000 users cached (and much more of guild members), but after you have all of them cached, it stops increasing (I have left my bot online for 28 days without reboot, increased from 65 to 180mb in 2 weeks and kept using around 200mb for the other two weeks).

However, discord.js does not keep all the data for forever. For example, if your bot leaves a guild, all the data related to it will be garbage collected. Just make sure you remove any reference for a very specific member, because if you keep one (which has a reference to the guild itself, which also has all the roles, members, channels, emojis...), the garbage collector may not be able to collect it and free the memory.

Wodki commented 6 years ago

Okay sounds good. Now is there a way to limit the member caching (aside from me not fetching the members on start). I saw that I can limit the message caching through the client options, but nothing about the members.

JMTK commented 6 years ago

See my comment

I've alleviated some of my issues by using guild.members.fetch(id) instead. It's seemingly gone away. I have 4 shards with ~30-40k users per shard.

iCrawl commented 6 years ago

1409