Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!


Is memory supposed to be "in use", or "cleaned up"?
New on LowEndTalk? Please Register and read our Community Rules.

All new Registrations are manually reviewed and approved, so a short delay after registration may occur before your account becomes active.

Is memory supposed to be "in use", or "cleaned up"?

JohnMiller92JohnMiller92 Member
edited March 2018 in Help

Long story short: I bought a cheap yearly VPS from snipped. I've been writing a game server in an awesome programming language called Crystal.

I was doing some testing with a lot of socket connections and am quite confused about memory usage. The crystal language uses a garbage collector, but it doesn't necessarily free the memory. It recycles, and then keeps the memory reserved to be used again (from what I'm understanding).

I posted a question about it here: https://www.reddit.com/r/crystal_programming/comments/7tgt4p/how_to_deallocate_memory_from_deletedunreferenced/

That means: If 5000 players log onto the server, let's say for example the memory usage goes to 500mb.

Then, at midnight, 4000 players log off. Shouldn't the memory be cleaned up, so the VPS doesn't utilize such high amounts of ram anymore? I don't understand the responses in my thread there

If anyone can help clear this up for me it'd be great, thanks in advance :)

Comments

  • AnthonySmithAnthonySmith Member, Patron Provider
    edited January 2018

    I have no idea but it sounds interesting and your avatar is top quality!

    Few keen coders around here so no doubt someone will understand/translate reddit for you.

    Thanked by 1JohnMiller92
  • svmosvmo Member
    edited March 2018

    @JohnMiller92 said:
    Long story short: I bought a cheap yearly VPS from snipped. I've been writing a game server in an awesome programming language called Crystal.

    I was doing some testing with a lot of socket connections and am quite confused about memory usage. The crystal language uses a garbage collector, but it doesn't necessarily free the memory. It recycles, and then keeps the memory reserved to be used again (from what I'm understanding).

    I posted a question about it here: https://www.reddit.com/r/crystal_programming/comments/7tgt4p/how_to_deallocate_memory_from_deletedunreferenced/

    That means: If 5000 players log onto the server, let's say for example the memory usage goes to 500mb.

    Then, at midnight, 4000 players log off. Shouldn't the memory be cleaned up, so the VPS doesn't utilize such high amounts of ram anymore? I don't understand the responses in my thread there

    If anyone can help clear this up for me it'd be great, thanks in advance :)

    • Imagine memory allocation as a growing apartment building, - as new tenants move in (log on) more floors ar added to the buolding. - eg memory is taken from the OS.

    • However when people move out (players log off) somone might still have space in use on the top floors. - So you can not reduce the height of the building without relocating stuff from the top floors.

    • That is mostly not doable with todays data structures - so you are left with a building with a number of emty apartments - which may of course be used when new tenanats move in again.

    tl;dr The application memory usage will grow and mostly stay at is max size - memory is not loast however it is available to your application but may not be available to the OS.

    If badly implemented usage might continue to grow until the application is restarted - you see that with web browsers with a lot of long running tabs open - even today - restarting the browser and letting it reload tabs may reduce memory usage drastically.

    Thanked by 1JohnMiller92
  • Uaually, it will be cleaned up when it needs to. In the meantime as unused memory is wasted memory, it will be used, then moved to inactive (could be used again quickly if needed) then cleaned when the OS decides it's the right thing to do.

    I don't know the specifics about GC though. On the link they gave you there are a few tips that seem worth trying.

    Thanked by 1JohnMiller92
  • JohnMiller92JohnMiller92 Member
    edited January 2018

    @svmo Wow, awesome analogy. That does help me understand it a bit better. I'm just so confused on this matter. I just don't really understand why the ram usage doesn't go back down. For example, when people move out of the building (log off), you say someone might still have space in use on the top floor. However, in my mind, they are vacated (not renting the room anymore), so their room is free (freeing ram). But in this case, the ram usage stays the same even after a user logs off. <-- Where my brain gets stuck

    Am I getting the ram usage mixed up with ram allocation or something?
    I mean, if 1 user is logged in, after 4999 logged off. I shouldn't have the ram usage of when 4999 are logged in, right? It just doesn't make sense to me :(

    For example, in the Godot engine if you fill up an array with thousands of values. You'll see memory usage increment to like 10mb usage. Then, if you run array.clear, Godot's memory usage drops down that 10mb. Since you free'd the memory.

    That's how I am viewing this dilemma. When the array get's cleared (users are logged off), the ram usage stays the same. I'm sorry if I'm making the process more confusing than it is, just trying to understand it better.

  • FHRFHR Member, Host Rep
    edited January 2018

    Maybe it's like Java. Even if it doesn't need the memory anymore, it will keep it allocated (with most GC types). Reason being that constantly allocating and freeing memory can be inefficient. This behaviour is fine in most cases, since server load is usually periodic, e.g. 5000 players join, this count drops to 100 at night and the next day you are back at 5000. You really should not have a reason to change this.

  • JohnMiller92JohnMiller92 Member
    edited January 2018

    @FHR Good point. One thing I've thought about, that could be really dangerous is: let's say you have a VPS with 4GB ram. And someone attacks it before, let's say fail2ban or your host can block it (or for whatever reason). Your memory usage spikes to 4GB to handle the load/new connections. And then now, your VPS will be utilizing 4GB Ram when you have a couple players online. I just don't get it :(. There has to be a way to free the memory I feel like >_<

  • perennateperennate Member, Host Rep

    Wow, awesome analogy. That does help me understand it a bit better. I'm just so confused on this matter. I just don't really understand why the ram usage doesn't go back down. For example, when people move out of the building (log off), you say someone might still have space in use on the top floor. However, in my mind, they are vacated (not renting the room anymore), so their room is free (freeing ram). But in this case, the ram usage stays the same even after a user logs off.

    The memory allocator is complicated and I don't know the specifics (it probably also varies from system to system), but I think this simple model is accurate enough: your Crystal program can reserve memory in units of floors. When players join, it needs more memory, so it reserves several floors to handle the players. When players leave, most of that memory is no longer needed, so many of the rooms on the floors are vacated. However, maybe each floor had a couple rooms (out of thousands of rooms) that were not vacated because the occupant is still there, maybe some persistent object or just one player that hasn't left yet.

    The memory is still used up by the program because the program can only release memory back to the operating system in units of floors. It cannot release any of the floors because although 99% of the floor is vacated, there are just a few rooms occupied on the floors.

    Of course you could image that the garbage collector could merge the small number of remaining occupants from all of the 99% empty floors into one floor, and then release the rest. Probably garbage collectors and/or memory allocators usually do something like this.

    The Boehm GC does not return heap memory back to the OS by default. This means that if you heap size grows, your app will allocate more memory and keep that memory allocated for the crystal process. If you look at the GC free memory from within the process you will see that it freed the memory to be used for new crystal objects. Freeing the memory will stop the heap from growing, but the process will still keep that memory for itself.

    But the person on reddit is saying that the Crystal garbage collector (I guess it's called Boehm GC) isn't designed to release the floors.

    From the Github discussion, it sounds like if you built Crystal (not using precompiled binary), then you can edit omnibus-crystal/config/software/bdw-gc.rb and add "--enable-munmap" after "--disable-shared" in the ./configure call.

    Thanked by 1JohnMiller92
  • @JohnMiller92

    You're free to limit its memory usage. You could use cgroups and allocate 95% to your program and leave 5% of the memory available for your system.

    Thanked by 1JohnMiller92
  • JohnMiller92JohnMiller92 Member
    edited January 2018

    @perennate said:

    The memory allocator is complicated and I don't know the specifics (it probably also varies from system to system), but I think this simple model is accurate enough: your Crystal program can reserve memory in units of floors. When players join, it needs more memory, so it reserves several floors to handle the players. When players leave, most of that memory is no longer needed, so many of the rooms on the floors are vacated. However, maybe each floor had a couple rooms (out of thousands of rooms) that were not vacated because the occupant is still there, maybe some persistent object or just one player that hasn't left yet.

    The memory is still used up by the program because the program can only release memory back to the operating system in units of floors. It cannot release any of the floors because although 99% of the floor is vacated, there are just a few rooms occupied on the floors.

    Aww. I think I am starting to understand it now! So.. once the floors are vacated, there is not necessarily a performance loss at all, right? Just makes the program have easier access to the rooms (since they've already been open)? So the high ram usage.. just becomes a highly amount of allocated space that can be accessed faster? If that makes sense?

  • FHRFHR Member, Host Rep

    If someone attacks your game server on layer 7 (meaning an application level attack, typical attack vector of game servers is spamming joining in and immediately disconnecting), there's nothing your host can do about it. You have to implement limits in your application. You should limit the maximum amount of simultaneous players and limit the maximum amount of memory the process can consume. Limiting the number of log-in attempts per IP and time (i.e. you can only join the server 5 times per minute and then your IP is banned for 5 minutes) is also a common mitigation technique. Set sane limits.

  • Just read your reddit thread.

    Why do you want the memory freed? Do you need the memory for something else?

    Apparently, whatever programming language you are using, prefers to keep the memory to itself and reuse it when necessary.

    If you have 5000 players with 500mb memory, then 4900 of those log off, you still have 500 mb memory, and this is bad because...?

    You should check whether the next day, when 4900 new players log in again, does your memory stay at 500mb or does it increase to 1 GB? If it increases with every new player but never decreases, that's a memory leak and should be fixed. But if it stays at the maximum as long as the same amount of players log in and log out, then why are you even worrying about the unused memory?

    Do you ask your hosting provider to disconnect the memory chips at nights, since you don't need it until the next morning? You keep the memory chips in the server, because you'll need them later. Crystal seems to do the same, it keeps the memory until it needs it later.

    Unless you need the memory for something else, just let it have it.

    Of course, if the usage keeps increasing while the average number of players are the same, then you have a separate problem, it's memory leak, not gargabe collection.

  • JohnMiller92JohnMiller92 Member
    edited January 2018

    @FHR I do use iptables and other rate limiting stuff, but I'm not going to sit here and say I'm immune to a DDOS attack. If that happens, the memory usage will go up on the VPS. I was just trying to give an example. If that were to happen, then essentially the game server will be utilizing 4gb of ram with a couple of players online. That makes zero sense to me. And it also seems like a waste of system resources, no?

  • perennateperennate Member, Host Rep
    edited January 2018

    JohnMiller92 said: Aww. I think I am starting to understand it now! So.. once the floors are vacated, there is not necessarily a performance loss at all, right? Just makes the program have easier access to the rooms (since they've already been open)? So the high ram usage.. just becomes a highly amount of allocated space that can be accessed faster? If that makes sense?

    I don't think holding on to the floors alone would make the program run faster. It is just that, the only way to release a set of floors is to move any of the 1% remaining occupants on each floor into a single floor, and then release the rest now that they are 100% unoccupied. I guess this is called "memory compaction" (trying to find a good blog post that explains all of this but none of them so far are concise :|).

    So if you choose to do this compaction, then the program has lower memory usage, but some extra time is needed to move the small number of occupied rooms.

    Because of that, holding on to the floors could make the program run faster, not because the rooms can more quickly be used the next time the program needs extra memory, but because it can skip this compaction step.

    Even if you don't do compaction, the memory is certainly not lost forever -- the program can use up the rooms the next time lots of players join (as long as there is enough space between the occupied rooms for whatever objects are being allocated: if room 102, 104, 106, and 108 are occupied, and you want to store a fat guy that is two rooms wide, then you can't fit him in room 105 or 107...).

    Anyway this might not be relevant to your case. Probably this "Boehm GC" does some sort of compaction? But whether it does compaction or not, the reddit person says that it doesn't actually release the memory to the OS.

    If you don't need the memory for other processes, then I don't think it's a problem for you (the program can still use the memory the next time objects are allocated). If you do want some memory to be freed so that you can run other things on the server, then you could look into that compiler option.

    Thanked by 1JohnMiller92
  • perennateperennate Member, Host Rep

    Hm so I finally found this blog post that might be insightful: https://blog.plan99.net/modern-garbage-collection-911ef4f8bd8e

    I haven't read the whole thing yet though, but so far some things it mentions are interesting to me.

  • williewillie Member
    edited January 2018

    The Boehm GC (hboehm.info/gc) does not move stuff around in memory when dead objects are freed. In the jargon, it is a non-compacting gc. In your hotel analogy, people vacate rooms and the rooms are made available for new occupants, but there's no attempt to consolidate the vacant rooms and free up whole floors. You could get a situation (heap fragmentation) where there are 1000s of vacant rooms, but they're scattered around the hotel so if a group of 20 people arrives and wants adjacent rooms, there's no block of them that large and the hotel has to build another floor (allocate more memory).

    If there's actual memory pressure then the OS paging system will eventually page out blocks of rooms that are empty or have quiet enough occupants. That can cause a performance hit if it happens too much and the pages have to be brought back in.

    I wouldn't worry about this too much if this is your first project and you're not trying to run other memory-hungry programs at the same time as your game server. Just use a big enough VPS to handle the max load. At worst you might have to restart the game server once in a while.

    Thanked by 2JohnMiller92 svmo
  • FHRFHR Member, Host Rep

    @JohnMiller92 said:
    @FHR I do use iptables and other rate limiting stuff, but I'm not going to sit here and say I'm immune to a DDOS attack. If that happens, the memory usage will go up on the VPS. I was just trying to give an example. If that were to happen, then essentially the game server will be utilizing 4gb of ram with a couple of players online. That makes zero sense to me. And it also seems like a waste of system resources, no?

    Really depends on the kind of attack. If it's a typical UDP flood, SYN flood etc (Layer 3/4 attacks), there are really only two options:

    • Your provider will mitigate it
    • Your provider will shut you down

    If your app is consuming 1MB or 512GB doesn't really matter in this scenario.

    If it's an application level (Layer 7), then this becomes much more interesting though... See my previous reply to this thread in this case.

    Generally you will be attacked on layer 3/4, as that doesn't require any work from the attacker, it's cheap and generally very effective.

    Thanked by 1JohnMiller92
  • JohnMiller92JohnMiller92 Member
    edited January 2018

    Okay. Think I got it now. These analogies are on-point and helped a lot, really.

Sign In or Register to comment.