allinurl / goaccess

GoAccess is a real-time web log analyzer and interactive viewer that runs in a terminal in *nix systems or through your browser.
https://goaccess.io
MIT License
17.78k stars 1.09k forks source link

Does goaccess respect docker mem_limit? #2645

Open rc5hack opened 3 months ago

rc5hack commented 3 months ago

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?

allinurl commented 3 months ago

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?

rc5hack commented 3 months ago

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.

rc5hack commented 3 months ago

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
allinurl commented 2 months ago

@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?