Does goaccess respect docker mem_limit?
When run with docker-compose, it seems that goaccess "knows" of mem_limit set on docker side:
configuration 1: mem_limit: 384m
version: '2.4'
services:
goaccess:
image: allinurl/goaccess:1.9.1
command:
- /path/to/logs
- --log-format=VCOMBINED
- --output=/path/to/report.html
- --real-time-html
- --ws-url=wss://${DOMAIN_NAME}:443/ws
environment:
- GOMEMLIMIT=320MiB
cpus: 1.00
mem_limit: 384m
RAM consumption with configuration 1: 360m (not great, not terrible)
docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
fe7834d3e921 goaccess 0.01% 360.3MiB / 384MiB 93.82% 31.8kB / 1.43MB 92.4MB / 0B 4
configuration 2: all the same, but mem_limit: 512m
version: '2.4'
services:
goaccess:
image: allinurl/goaccess:1.9.1
command:
- /path/to/logs
- --log-format=VCOMBINED
- --output=/path/to/report.html
- --real-time-html
- --ws-url=wss://${DOMAIN_NAME}:443/ws
environment:
- GOMEMLIMIT=320MiB
cpus: 1.00
mem_limit: 512m
RAM consumption with configuration 2: 401m (even more than previous maximum limit?! how???)
docker stats --no-stream
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
7c048f6d8a92 goaccess 4.87% 401.2MiB / 512MiB 78.36% 98.1kB / 19.2MB 176MB / 0B 4
Thus, the higher mem_limit value becomes, the more RAM application consumes under identical conditions.
This behavior is strange, because goaccess remains the same and the logs it processes remain the same. It seems that goaccess somehow respect the mem_limit value and changes the behavior depending on it. This is usually not the case: applications running in Docker don't "know" about mem_limit value and don't respect it's changes out of the box.
Deleting GOMEMLIMIT variable changes practically nothing in this configurations.
Does goaccess intentionally respect docker mem_limit really?
Nope, GoAccess isn't aware of Docker's mem_limit. This behavior might be because of how Docker handles memory limits and how goaccess responds to them. I'm not entirely sure about the specifics of Docker's mem_limit, but I guess it doesn't instantly shut down a process when the limit is hit. My guess is that Docker might employ memory swapping and compression instead?
Nope, GoAccess isn't aware of Docker's
mem_limit.
Okay, it does matter. I should make some more tests with numerous runs to reproduce this behavior under controlled conditions. It seems like some garbage-collection trait on GoAccess side, but I can't proof for now.
Docker ... memory swapping
Maybe...
Docker ... memory compression
Very questionable. Docker definitely does not implement memory compression on its side, memory compression is a kernel feature, not a Docker feature. This way, memory management should not be different when GoAccess is running in docker or without it.
I hope to explore this in more detail and come back here with more results.
For those who end up here in the future investigating similar issues:
In my 1st post, given configuration example could be confusing: I used GOMEMLIMIT env variable, which is suitable for golang-based software only. GoAccess is written in C, hence GOMEMLIMIT is entirely useless and should not be used here (it might make sense to add a line about this in redme).
environment:
- GOMEMLIMIT=320MiB
@rc5hack Thanks for sharing those findings. I agree. Could you quickly submit a PR to add that to the Docker section in the README.md?