This is solved pretty easily in Java using soft references and a hard memory 
cap. 

Similar techniques may work here. 

> On Jan 20, 2020, at 11:22 AM, Christian Mauduit <uf...@ufoot.org> wrote:
> 
> Hi,
> 
> That is a generic question and I think that if you want to keep an approach 
> with a "global indicator of how much memory is used", your approach is OK. 
> You might also want to store this information of "should I throttle" in a 
> cache or something, the cache could be just a shared atomic flag.
> 
> But, from my experience, ugly OOMs can come very fast. So a ticker might just 
> not catch them. On modern hardware, you can allocate gigabytes of memory 
> within seconds, and hit the roof before your ticker based watcher notices 
> anything.
> 
> The best rules I have seen to enforce proper memory control is:
> 
> - channels are blessed as they are limited in size
> - bind everything else to a limit. More specifically, enfore limits for:
>  - maps (limit the number of entries)
>  - arrays
>  - generally speaking, anything which can *grow*
> 
> It is tedious, but on top of avoiding the "my ticker does not run often 
> enough" problem, you will also be able to take a decision (should I allocate 
> or not) based on local, actionable facts. The problem with the global 
> approach is that at some point, when the program is running out of memory, 
> you will not know *WHAT* is taking so much space. So you might end up 
> stopping allocating Foos when the problem is that there are too many Bars 
> allocated. I have seen this happening over and over.
> 
> So from my experience, just:
> 
> - observe, monitor your program to see what is taking most memory
> - enforce limitation on that part to ensure it is bounded
> - make this configurable as you will need to fine-tune it
> - write a test that would OOM without memory control
> 
> Sometimes the naive approach of those low-level limits does not work.
> 
> Example: you have a map[int64]string and you can affort ~1Gb for it, but the 
> size of string can range from 1 byte to 1Mb, with an average of 1Kb, and you 
> need to store 1M keys. With such a case, if I want to be serious about OOMs 
> and if it is a real problem, I would bite the bullet and simply track the 
> total amount of bytes stored. Maybe not the precise amount of data, summing 
> the length of all strings could be enough.
> 
> But the bottom line is -> I fear there is no "one size fits all" solution for 
> this.
> 
> It is expected that library providers do not implement this as they wish to 
> offer generic multi-purpose tools, and memory enforcement is rather an 
> application, final-product requirement.
> 
> Best luck, OOMs are hard.
> 
> Christian.
> 
>> On 20/01/2020 09:22, Urjit Singh Bhatia wrote:
>> Hi folks,
>> I am trying to figure out if someone has a decent solution for max memory 
>> usage/mem-pressure so far. I went through some of the github issues related 
>> to this (SetMaxHeap proposals and related discussions) but most of them are 
>> still under review:
>>  * https://go-review.googlesource.com/c/go/+/46751
>>  * https://github.com/golang/go/issues/16843
>>  * https://github.com/golang/go/issues/23044
>> My use case is that I have an in-memory data store and producers can 
>> potentially drive it to OOM, causing the server to drop all the data. I'd 
>> like to avoid it as much as possible by potentially informing the producers 
>> to slow down/refuse new jobs for a bit till some data is drained if I has 
>> some sort of a warning system. I think rabbitmq does something similar  
>> https://www.rabbitmq.com/memory.html
>>  * How are others in the community handling these situations? It seems
>>    like most of database-ish implementations will just OOM and die.
>>  * Has anyone implemented a mem pressure warning mechanism?
>> Does something like this make sense for detecting high mem usage? (Of course 
>> other programs can randomly ask for memory from the OS so this isn't going 
>> to be leak-proof)
>>    funcmemWatcher(highWatermarkuint64, memCheckIntervaltime.Duration) {
>>    s:=&runtime.MemStats{}
>>    // Count how many times we are consecutively beyond a mem watermark
>>    highWatermarkCounter:=-1
>>    forceGCInterval:=10
>>    forrangetime.NewTicker(memCheckInterval).C {
>>    runtime.ReadMemStats(s)
>>    ifs.NextGC >=highWatermark {
>>    log.Println("Approaching highWatermark") // Approaching highWatermark
>>    continue
>>    }
>>    // Crossing highWatermark
>>    ifs.HeapAlloc >=highWatermark {
>>    ifhighWatermarkCounter <0{
>>    // Transitioning beyond highWatermark
>>    log.Println("High mem usage detected! Crossed high watermark")
>>    // Start counters
>>    highWatermarkCounter=0
>>    forceGCInterval=10
>>    log.Println("Reject/Throttle new work till usage reduces")
>>    continue
>>    } else{
>>    // Still above highWatermark
>>    highWatermarkCounter++
>>    ifhighWatermarkCounter >=forceGCInterval {
>>    log.Println("Forcing GC...")
>>    runtime.GC()
>>    forceGCInterval=forceGCInterval *2 // Some kind of back-off
>>    }
>>    }
>>    } else{
>>    ifhighWatermarkCounter >=0{
>>    // reset counters - back under the highWatermark
>>    log.Warn().Msg("Mem usage is back under highWatermark")
>>    highWatermarkCounter=-1
>>    forceGCInterval=10
>>    }
>>    }
>>    }
>>    }
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to golang-nuts+unsubscr...@googlegroups.com 
>> <mailto:golang-nuts+unsubscr...@googlegroups.com>.
>> To view this discussion on the web visit 
>> https://groups.google.com/d/msgid/golang-nuts/3408da0e-f420-4b3d-98f0-d0a06e95d398%40googlegroups.com
>>  
>> <https://groups.google.com/d/msgid/golang-nuts/3408da0e-f420-4b3d-98f0-d0a06e95d398%40googlegroups.com?utm_medium=email&utm_source=footer>.
> 
> -- 
> Christian Mauduit            __/\__  ___
> uf...@ufoot.org              \~ ~ / (`_ \   ___
> https://ufoot.org            /_o _\    \ \_/ _ \_
> int q = (2 * b) || !(2 * b);   \/       \___/ \__)
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to golang-nuts+unsubscr...@googlegroups.com.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/golang-nuts/3ddf2728-ec41-303c-12e2-bf378ba67cc7%40ufoot.org.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/D400BDD7-9DF5-4D19-92F3-8DD5A78D56D7%40ix.netcom.com.

Reply via email to