On Fri, 16 Apr 2021 at 02:21, Kevin 'ldir' Darbyshire-Bryant <l...@darbyshire-bryant.me.uk> wrote: > > > On 14 Apr 2021, at 00:34, Simon Kelley <si...@thekelleys.org.uk> wrote: > > > > Tagging onto the end of the thread just to report the results of my > > research. > > > > This started because of problems with the OOM killer in a > > resource-constrained system that was prompting OOM death when it spawned > > sub-processes to handle TCP connections. I proposed a trick of putting > > the large in-memory dataset in sub-process, so that the main dnsmasq > > process which forks to handle TCP requests stays small. Reading around, > > that probably won't work: the OOM killer weights size of all children > > when looking for a victim. I think that trying to outsmart the OOM > > killer is probably a hiding to nothing. It's possible for the OS to > > protect critical daemons using oom_adj and friends, and supporting that > > in OpenWRT looks like a better way to go. > > > > We then moved onto the fact that adblocking involves thousands of lines of > > > > local=/example.com/ > > > > and the code supporting that didn't really envisage such large numbers. > > I think improvements can be made there, and I'll look at doing that in > > more detail. > > Hi Simon, > > Thanks for picking this up again. There are multiple interlinked problems: > > (ab)use of local=/example.com/ or similar for adblock lists which leads to > memory usage & (apparently) slower response time due to the linear search of > ’servers’ handling the local domain. I’m sure the ‘local’ list could be put > into some sort of tree/hash structure to speed that up but the memory > consumption will inherently be there to some (hopefully optimised) extent. > The list has to exist :-) > > TCP requests causing a fork of dnsmasq with all that ‘local/server’ list > memory usage, up to 21 times. I’m looking at my APU 2 running openwrt at the > moment with a 46000 line (small) adblock ‘address=/foo.bar/‘ list - dnsmasq > consuming circa 12MB. 21*12MB 252MB isn’t going to cause my APU to sweat > memory wise but a lesser device could very well ask ‘Where am I going to find > this extra 228MB of memory from then?’. > > I don’t agree that your ‘large dataset sub-process with small tcp handling > children’ won’t work. Yes linux oom killer takes into account all the > children, but the tcp children are going to be much(much!) smaller, > presumably the size of a basic dnsmasq instance of which most of it will be > program text. A base dnsmasq on said APU2 takes 2.5MB (the above example > would then total 12MB + 20*2.5=62MB) That’s quite a difference on a > constrained system between asking for lumps of 12MB vs 2.5MB. Whether this > approach makes sense from a latency perspective I don’t know… I’m assuming > that large process is acting as an ‘address validator’ and hence the > requesting children will need to wait for its ‘yes/no’ answer subject to > process scheduling etc. > > Tony mentioned another possible solution which avoids the sub-process malarky > of marking the ’server list’ memory in some way that the OS knows it’s shared > and therefore don’t need to have ‘real memory’ for all those tcp > sub-processes. I’m sure he’ll be along in a minute to explain further. >
Hi Simon, Kevin, I wrote a test program that emulates dnsmasq execution when loading large blocklists and then forking children to handle TCP DNS requests. It allocates memory and initializes it, then sets it read-only, and finally forks a number of child processes. At each step, it prints committed memory from /proc/meminfo, tracking the risk of OOM. The option "--private" uses private anonymous memory and reproduces normal dnsmasq behaviour; it can easily trigger OOM on small memory systems (e.g. 128MB). The other option "--shared" demonstrates how using shared anonymous memory reduces the overall commit and can work on even small systems. I also captured some log files from running on a "big" 8GB system and a "small" 128MB OpenWrt system. Using shared memory on the "small" system, I can allocate 64 MB without issue, while doing the same using private memory is a reliable way to trigger OOM. For more details see the head commit and related files here: https://github.com/guidosarducci/dnsmasq/commits/oom_alloc_test/ Best regards, Tony _______________________________________________ Dnsmasq-discuss mailing list Dnsmasq-discuss@lists.thekelleys.org.uk https://lists.thekelleys.org.uk/cgi-bin/mailman/listinfo/dnsmasq-discuss