Really interesting and instructive. Let me see if I understood properly:

Considering the below explanation, an idle (not going to receive more messages the next 7 days) imrelp rsyslog...shouldn't memory be freed from current 512MB usage in the near future?

You mentioned forcing each 100.000 messages, but that's never gonna happen if we are still at 20k, and no more messages coming.

Regards


El 19/01/17 a las 11:16, Rainer Gerhards escribió:
2017-01-19 10:19 GMT+01:00 mostolog--- via rsyslog <[email protected] <mailto:[email protected]>>:

        with very few exceptions, rsyslog releases the memory as it
        goes, there should not be any significant amount of memory
        freed by rsyslog after it's been idle for a while.

    But being idle for 15m should release memory from 512MB to a few
    KB if they aren't used, isnt it?


Memory alloc is not as simple as it seems ;-)

First, clib does not always do a proper cleanup. I guess it seems not to consolidate free space in all cases. There is a clib call to force this, and rsyslog does it from time to time (I think every 100,000 messages). We do not do it very frequently, because it is an expensive operation. Also note that memory is reusable internally, so even though it is not returned to the OS, further alloc requests inside rsyslog can use this memory and do so. Returning memory to the OS and re-claiming it is expensive. Thus you do want to keep some memory allocated but internally unused to avoid doing this operation too frequently.

Secondly, memory alloc from the OS is done by sbrk[1] IIRC. The important point is that we need to alloc and free memory in sequence. This means if you alloc 100MB, than alloc 1MB, you have the following memory layout

BASE
100MB
1MB

with the break at BASE+101MB. If you now free the 100MB chunk, you have this layout:

BASE
100MB free
1MB

if you want to return to the OS, you'd need to copy down the 1MB to immediatly after BASE, because otherwise you cannot reset the break to BASE+1MB. The allocator does not do this, it would totally wrek performance (note: that is not rsyslog specific, that is how the *C runtime* works). More importantly, it would mean all pointers to it would need to be updated. And the runtime does not know where these pointers are located. So it would not only costly, compaction is simply impossible. Let's assume we now alloc another 10 MB. Then we have

BASE
10MB
90MB free
1MB

because the allocator uses the free, but still allocated mem. Now, let's assume we free the 1MB chunk, we get:

BASE
10MB
91MB free

Now the free space is at the end of the data segment. So the alloc subsystem has the choice to reduce memory alloc from the OS. It may or may not dealloc. I don't know the exact rules, but the important thing is that the alloc system uses some heuristic (plus the call I mentioned) to decide if to dealloc. Let's assume it does. Then it reduceds the data segement size and we get to

BASE
10MB

effectively reducing rss by 91 MB.

IMHO the alloc system strongly works on the assumption that memory allocated (from the OS) but free internally does not really hurt, as it is just virtual address space, which, if actually unused, is paged out to disk once and then doesn't matter at all until it get's reused again.

OF COURSE if we have constantly growing memory, the app seems not to free some chunks, so the alloc system doesn't know they are free. This has nothing to do with what I explained. What I explained just means that an app may do proper free()'s, but the rss size doesn't reflect this. The typical (and often visible) effect of that is that the app grows to a certain size and then remains at it (no growth, no decrease). This is where, via the clib call, we force free.

There is one important point, though: if we have a memory block at the far end of the data segment, we cannot return mem to the OS until this block has been freed. In rsyslog, you typical see this if

a) old-style "last message repeated n times" is active
b) an infrequently written-to output stores a message object when queues are very full
c) no different messages are written to that output for a long time

What here is very probably that in b) a high memory address is used for that memory block. As due to c) we do not have any traffic, that high address is kept in use for hours, maybe days. Once a different message arrives at the output, the old object is processed and freed. This can result in a very sharp decrease of rss size, especially if the system has low load during such times. Let's assume this layout:

BASE
10MB used
1.5GB free, but allocated from OS
5k msg object

If we now free those 5k, most probably the alloc system heuristic will immediately return 1.5GB+5K to the OS, reducing the rss size accordingly.

Bottom line: not everything that looks like a memory leak actually is one.

HTH
[1] https://linux.die.net/man/2/sbrk

_______________________________________________
rsyslog mailing list
http://lists.adiscon.net/mailman/listinfo/rsyslog
http://www.rsyslog.com/professional-services/
What's up with rsyslog? Follow https://twitter.com/rgerhards
NOTE WELL: This is a PUBLIC mailing list, posts are ARCHIVED by a myriad of 
sites beyond our control. PLEASE UNSUBSCRIBE and DO NOT POST if you DON'T LIKE 
THAT.

Reply via email to