Is there a way to limit the "buffer" memory use in Linux?
I'd like to limit a Linux server's assignment of RAM into the disk cache buffer and instead leave it idle. (CentOS 5 if it matters). I know it's ideal to be using every drop of physical RAM available for something even if just caching disk - Linux is great at that. Most of the time I wouldn't even consider trying to defeat this. Let me tell you why I want to (I am not concerned about monitoring):
My company has a contract with a 3rd party for some VMs and we have a committed memory limit included in our monthly bill. Overages are crazy expensive. 2 of these VMs run an application which just chews RAM during the process startup, but once stable, usage drops down a lot. Devs assure me that's what this service is supposed to do and isn't going to get "better" any time soon. So I keep these VMs provisioned with around 2x the RAM usually needed in normal run mode. Once stable, the extra just gets thrown into the buffer cache and everybody's happy. Except the finance guys.
Our provider counts RAM allocated to the buffer cache against our committed total amount for the virtual data center, hence we pay for that every month. A lot. I don't believe I care about whatever is cached - I'd be happy to run with less RAM (ie less cache) and take a bit of a performance hit on the file access (I assume...) except when the app starts up from scratch and needs that RAM to not actually swap to hell and back.
So I'm looking for a way to tell Linux something like "hey, only ever use 1GB (or better, x%) of free RAM for disk cache buffering, yep, just go ahead and waste the rest of it!". We could save a lot of $ over the years since if that RAM was actually kept free and not allocated to the buffers, it wouldn't count against our committed amount and we wouldn't have to "rent" it. But since something is using it, even if it's just the buffer cache, we pay for it.
I've searched around a lot, and mostly see questions like "OMG why is my server nearly at 100% all the time..." and people freaking out about their monitoring/alarm/nms and getting educated by the responses - that's not my question; I had those same reactions 10 years ago but in this case I really want to actually not use that RAM so I don't have to "pay rent" for it when the app doesn't need it.
Alternate suggestions welcome if you think of another way to accomplish this.
Thanks much...
Solution 1:
I don't know if you can prevent caching, but you could regularly ask linux to drop the cache.
The way to do it is explained there: https://unix.stackexchange.com/questions/87908/how-do-you-empty-the-buffers-and-cache-on-a-linux-system
If you sync
just before the echo to /proc/sys/vm/drop_caches
command, it should free a lot of ram.
Linux will not actively fill your ram by opening files and caching them. Only the files that are actually active will be cached. That can be the files used by your application, including the program's binary code.
It can also be the log files. You could use network logging to avoid that.
Another approach could be to run your application in a virtual machine, with much less ram, and a ram-disk as swap device (and then control the sappiness level), but it's a bit more complicated.
I wonder how your provider knows how much ram is allocated but not used by your system. Those pages of ram, even if not used, will not be empty.
Solution 2:
If cache is created by this application I think you could use cgroups after app is stabilized:
Create a cgroup named like group1 with a memory limit (of 50GB, for example, other limits like CPU are supported, in example CPU is also mentioned):
cgcreate -g memory,cpu:group1
cgset -r memory.limit_in_bytes=$((50*1024*1024*1024)) group1
Then bring app into this cgroup after startup:
cgclassify -g memory,cpu:group1 $(pidof your_app_name)
Solution 3:
vm.min_free_kbytes looks like it could help. Eg. executing
echo 524288 > /proc/sys/vm/min_free_kbytes # Value should be in MB
would force the system always to keep 512MB RAM free. In case a process needs the memory it will get it, after that the system will struggle to free that amount of memory again, possibly by freeing buffer cache or swapping out other processes. You could set this parameter after you application has started.