R
R
raiboon2021-01-01 23:47:13
go
raiboon, 2021-01-01 23:47:13

What approaches are there to stabilize the memory consumption in a Go application?

How can I stabilize the memory consumption of services so that they always consume plus or minus the same amount of memory?
I work in a large company, I have my own k8s cluster.
I own not very loaded microservices, on average it consumes tens of megabytes, but users periodically come and the load grows uncontrollably, there are light requests, and there are when the user requests a bunch of data (with a maximum limit in the interface) and if there are a lot of them, the service crashes by oom.
What to do?
On the one hand, cuboadmins do not want to allocate more resources - on average, consumption is scanty, they offer to deal with memory consumption on their own and threaten that they will soon tighten the screws, and it will not be possible to set a limit different from the request.
You can, of course, go to the administrative resources and allocate as much as I ask.
But still, it is not clear how much to ask.
Maybe there are some approaches to stabilize memory consumption?
In general, it is not clear how many resources to require if the load is unstable. Now it works due to the fact that the limits are set to an average meager memory consumption of 32-64 MB, but the limits are twisted into gigabytes, so that while one service responds to large chunks of data, others are unlikely to need this memory. But there is something wrong with this.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
L
Lynn "Coffee Man", 2021-01-02
@Lynn

To consume less memory, you need to consume less memory.
Since there is no specifics in the question, here are some general considerations:
For example, if you were asked for 1000 elements, then do not subtract all 1000 from the base, but read 10, send part of the answer, read the next 10 and so on.
The second approach is to limit simultaneous "heavy" requests - if you are already processing a "heavy" request, then the second such request should be queued and processed only after the first one is completed.

W
WinPooh32, 2021-01-02
@WinPooh32

If you need to mutate many strings, then don't use strings, but work with bytes. The bytes package is helpful.
Use sync.Pool to reduce the number of allocations.
Limit the number of concurrent requests. Here I can advise you to use a semaphore with weights. The idea is to give each request its own weight and, if the semaphore overflows, stop processing new requests until the resource is freed. The main thing here is to introduce a limit on the maximum number of connections, after which you can drop requests (now you essentially have the same thing happening, but due to a drop in the service, which is much worse).
In the most extreme case, you can ask the runtime to free the occupied memory:

runtime.GC()
debug.FreeOSMemory()

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question