My Discord app is using all my memory. What am I doing wrong?
I'm making what I thought was a simple dice rolling app for Discord. The user tells it how many dice to roll, any static modifiers to the total, and an optional description for the action being taken.
However, when I run the app I can only do a small handful of commands before my computer tells me that VS Code is using too much memory and I need to close it down. Sometimes the console even says something about heartbeat being too slow and a possible thread starvation.
I don't have that much code written so I'm not sure what's going on, but here's what I currently have:
43 Replies
nothing stands out as immediately wrong... the warning about potential thread starvation is interesting, since the only thing here I can see which would spin up more threads is just receiving requests to your endpoint.
i would try trimming out as much of the code as you can (sticking a 'return' at some early point in your MapPost, for instance) to see what minimal example you can get which reproduces the issue
if you're doing this in visual studio, use the memory profiler and observe how memory usage changes as you execute commands
they're in vscode
but i would second that recommendation
shit, missed that part
need more caffeine :Smug:
VS Code on Mac
Though now I'm wondering if it's the VS Code terminal. I'll try running it from the actual terminal to see if anything changes
Well I was able to run a lot more commands before the out of memory alert popped up…but it still popped up. I guess I'll throw up some early return statements to see what I can find out
what is the specific error message you're getting related to heartbeats and thread starvation, out of curiosity?
As of "08/16/2024 17:16:46 +00:00", the heartbeat has been running for "00:00:01.0572152" which is longer than "00:00:01". This could be caused by thread pool starvation.
ah, ok. searching that up confirmed this error is coming from within aspnet core
i would suggest reading through this https://learn.microsoft.com/en-us/dotnet/core/diagnostics/debug-threadpool-starvation
Debug ThreadPool Starvation - .NET
A tutorial that walks you through debugging and fixing a ThreadPool starvation issue on .NET Core
and specifically trying out dotnet-counters
it should let you hopefully get a better view on when new threads are being spawned
how are you testing this, by the way? could it be an issue where you're triggering your endpoint way more frequently than intended, by some misconfiguration with discord?
I added in early return statements at various parts of the code and have found the error to happen somewhere in here:
I'm running it on localhost and using NGrok to tunnel to my machine and running the slash command in a test server
🤔
how strange...
So it seems the issue is in the
DiceRoller
classthe only possible thing I can think of is that you're maybe instantiating the diceroller way more than you expect to, somehow
since there's nothing in there doing anything relating to threading
what if you remove all the calls to Random.Next() and replace them with hardcoded values?
Would it be better to register it as a singleton or something? So I'm not making a new one for each API call?
i'd register it as a singleton, don't see much point in making a new instance of it every time
plausibly, though i would be really surprised if a class that lightweight is causing issues
my only guess is that something could maintain a reference to it, so it (or something it uses) never gets GC'd.... but it doesn't look like that should be the case anyways so i'm not sure
i will be fascinated to find out what the root cause of this is
memory profiler of any kind would make this super simple to debug :pepeHands:
Is there a memory profiler for VS Code for Mac? Or is that something I need to find on the machine itself?
honestly not aware of any good profilers for mac
not sure if visual studio community has a mac build either (iirc VS for mac is getting discontinued soon anyways?) but it's something you could check
but i would go with bec's advice and see what happens when you get rid of your
Random
calls
you can also make your normalDice
and WildDice
arrays static, no reason to instantiate those each timeIf I do that would I need to instantiate a new
Random
inside each, then? Or how does class properites work for static methods? I'm still pretty new to C# and .NET so I apologize that I don't know how things workyou can use the Random.Shared property to have only one instance of it
How do I do that?
a static property inside a class means it essentially only exists once, no matter how many times you new() up the class
Oh, I see how!
as in, you can write 'var number = Random.Shared.Next()';
Static Classes and Static Class Members - C#
Static classes can't be instantiated in C#. You access the members of a static class by using the class name itself.
some relevant docs on statics in c#
Thanks!
Well, tried to replace the
Random.next()
calls with a pre-defined array of indices and I wasn't even able to call the command once before it shat the bed 😭
Is it because I'm using records instead of classes? I Thought they were supposed to be more efficient for "dumb data containers". It can't be that I'm doing too many lists, right? I'm gonna take a break and come back later with fresh eyes. Maybe something will pop out at me…
(I also made the two dice arrays static so the static methods could use them)there is definitely something extremely strange going on here that is not at all obvious from your code
so i highly suspect something weird in your environment or testing mechanism
it's a shame you don't have good profiling tools on mac...
maybe you can resort to logging Thread.CurrentThread or something lmao
to see when new threads are being spawned
So I have no idea WTF I did or didn't do…but it's been fixed?
I ran the command over 30 times in a row and there's a bit of lag, but I assume that's because of NGrok and when it's on a real server it'll be faster
The
Dice.cs
file is the only one I made any changes to:thimking:
what were the changes?
using shared random it seems
Shared random, yeah, and for some reason the class name was originally
public class DiceRoller()
instead of public class DiceRoller
. I assume the ()
did something wonkyi think the () would've just added a 'primary constructor' that did nothing
which was likely not relevant
interesting that using random.shared had that big an impact
it would imply you were creating a truly massive number of DiceRollers
No idea why that is, but at least it's working better now. Next step is to get the rest of the functionality working (asking for description of the action behind the dice roll) and then getting a single DLL or whatever to upload it to my linux server. My other Discord apps were written in Node.js and Go…so this is my first C#/.NET Discord app!
🙂
congrats!
Thanks for the help, (other) bec! lol
lol
no worries
If y'all wanna see it in action it's up and running!
https://discord.com/oauth2/authorize?client_id=1274372466642260072