Recently I received an alert that the memory utilization on one of my servers was more than 85%.
Now, this is an SQL server running on a Windows machine. My first reflex was let’s set an upper limit to the memory that the SQL server can utilize.
When I tried to do that, I found out that it already had a memory limit set. SQL server was clearly not the culprit here.
Long story short, the task manager showed RAM to be under control and the metric that CloudWatch was reporting was committed memory.
This lead me to think of the difference between these two, and what is committed memory, to begin with?
After spending hours and gathering bits and pieces from many different sources, I was able to put all the pieces together.
This blog post is basically all of that distributed knowledge condensed together to make better sense.
But, to start with…
What is memory?
We all say that the server has high memory utilization. What exactly do we mean by it?
Mostly we think, or at least what the first thought is, that this is the RAM utilization on our server.
But when we go on a bit detailed level, we see that memory is actually more than that. It is the entire virtual address space.
This includes RAM plus our page file (or files). We sometimes refer to the page file as a swap file.
Okay so now we know that RAM + page file is my total memory.
But wait a minute, what is a page file and how do we use it exactly?
Before we get into page files, there is a concept which we should understand first – committed memory.
Committed Memory
As the name suggests this is the memory committed.
But who committed it, to whom and why?
Say, for example, we have an application fulte_recorder. When we launch the application, it goes to the OS and says
“Hey, I need 750MB of memory”
OS, being the caretaker of all, checks its records and sees that we have 1600 MB of available memory.
It says that “Okay, I give you 750 MB memory”
The OS is now left with only 850 MB of available memory
And did I mention that flute_recorder only needs 130 MB memory anytime it runs?
Well the remaining memory is just in case I record piano in that app and it goes crazy 😛
So what is happening here is that though only 130 MB of memory is being used, an entire 750 MB memory is allocated to the flute_recorder.
This means that we have 620MB of memory allocated to flute_recorder which it is not using.
Now though we have 1,470 MB (620 + 850) remaining memory, the available memory is only 850 MB
The OS has committed a full 750 MB of memory to the flute_recorder app, and whether the app uses it or not, OS will not let anyone take it
Why do we need committed memory?
One thing that came to my mind after I read this concept was,
“If we are wasting memory because of committing it to some stupid application which is not using it, then why commit memory at all? Why are we wasting memory?”
I hope I’m not alone and you must’ve thought of this as well.
So now let’s say that we have a total of 100 MB of memory.
Flute_recorder app says that I need 80 MB but I’ll use only 20MB. And the OS goes like
“Take only what you need, don’t be greedy!”
The OS then allocates only 20 MB to the flute_recorder app.
Immediately after this, the paint_brush app says
“Hey, I need 90MB of memory but will use only 60 MB. Can you please give it to me?”
And the OS gives it the 60 MB that it will use.
Now we have only 20 MB of free memory. 60 MB went to paint_brush and 20 MB to the flute_recorder.
I have created an amazing flute recording, done most of the editing, and want to remove some background noise.
Lucky for me, the flute_recorder app has a plugin that I can use. So I go and enable the plugin.
The flute_recorder app now goes to the OS and says
“Hey, remember I was asking for 70MB of memory and you gave me only 20? It seems that I’ll need the other 50MB now. Can you please give it to me?”
This is where OS realizes that it messed up. It says
“Umm..I have only 20 MB of it. I gave the rest to paint_brush. Will this be sufficient for you?”
At the same time, the paint_brush app comes to the OS and says
“Hey, the other user there wants to import custom fonts. Can you please give me 30 MB more? I told you about it earlier, right?
The OS is scared now. It says
“I don’t have it. You’ll have to wait till flute_recorder frees some of the memory”
Now, this is where the revolution begins and both the apps, paint_brush and flute_recorder, crash.
And did I mention I spent 3 hours creating those masterpieces?
How can committed memory resolve this issue?
Let’s say that when flute_recorder asked for 70 MB, the OS gave it all. It says that
“No matter what happens, you’ll get your 70 MB. I promise”
Now when paint_brush asks for 90 MB memory, the OS says
“I’ve already committed 70 MB to flute_recorder, I can’t give you 90 MB memory”
And the app does not start at all.
Isn’t this a usability issue? Yes, it is – I can’t use paint_brush and flute_recorder at the same time.
But, now my three hours’ worth of effort won’t be wasted!
And this is why we use committed memory in the first place. So that none of our running applications die unexpectedly because of no memory.
You’ll face the downside of this only if you try to run SQL server, elasticsearch, and android studio on a 4 GB memory at the same time.
Otherwise, it’ll always save you unexpected crashes and data loss.
So now we know, that free memory is not always useable.
We have a part of our memory that can’t be used because it is reserved for some other application and that is the committed memory.
With this new insight, let’s see what page files are and how they work.
What is a page file?
Say for example we have a RAM of 4 GB. Now our applications have only 4GB of memory space available which they can use without impacting performance.
But what if I want more than 4GB of memory? I go to the market, buy some extra RAM and add that to my server.
And boom! It’s working faster now.
What if I can’t afford an additional 4GB of RAM? Or what if we can’t add more RAM to our system?
We’re doomed, arent’ we?
This is where page files come into the picture.
A page file is nothing but some space on the main storage (the hard drive) which appears to the applications as RAM.
Continuing our previous example, where flute_recorder reserved 70 MB of memory for itself and we are now left with only 30 MB
When paint_brush asks for 90 MB the OS doesn’t have that much memory. Let’s assume that we created a page file of 100 MB.
Now when paint_brush requests for memory, the OS thinks
“I don’t have 90 MB of available RAM but I do have 130 MB of virtual memory.”
It then looks at the flute_recorder app and continues thinking,
“It will never know the difference”
With an evil smirk on its face, the OS says
“Hey, take it – I have plenty of memory with me”
Wait a minute – if we can use cheap storage as virtual memory, why do we spend money on these expensive RAMs?
Why use RAM at all when we can use page files?
Now, this part is tricky.
We have a total of 200 MB of virtual space but only 100 MB RAM.
Flute_recorder app has 70 MB reserved and paint_brush has 90 MB reserved.
I’m doing some small tasks on my flute_recorder app so it is only consuming 10 MB of RAM, while the paint_brush app is using 60 MB of RAM
I then turn on that memory-eating plugin in the flute_recorder app. The app goes to the OS and says
“Hey, I reserved 70 MB and I’m only using 10 MB right now. Give me the remaining 60 MB”
The OS checks and finds that paint_brush is using 60 MB of RAM and so it only has 30 MB free (remember that flute_recorder is also using 10 MB RAM)
So the OS pushes the infrequent pages from the memory (read RAM) allocated to the paint_brush app out to the page file till the time it does not have 60 MB free in its RAM.
It then assigns that 60 MB to the flute_recorder.
And now if paint_brush comes and asks for memory, it will do the same with flute_recorder’s memory.
Basically, to the applications, all of 200 MB appears to be the RAM, but our OS quickly shuffles pages between the RAM and the page file. This ensures that both of our apps get a fair share of their allocated space whenever they need it.
And as our OS thought earlier, what will they know \_(-_-)_/
In very simple terms, RAM is where the action happens and the page file is just a quick backup of RAM which our OS uses to store the contents of RAM when some other application is using the RAM.
Ideally, the size of the page file should be at least equal to the size of the RAM. This is so that in case of system failure, we can store the crash dump in the page file.
One more question can arise at this point, what if flute_recorder is using all of 70 MB and the paint_brush also wants to use its 90 MB? We only have 100 MB of RAM, right?
This is where you will see a lag or a frozen system or the system might not respond. It may even slow down a bit.
But as soon as one of them reduces the memory consumption, things will be back to normal
This is how the entire thing works – it is just a fast chip combined with some cheap space and a cunning and hard-working OS