Tuesday 10 November 2015

Linux Memory - free command only shows used allocated memory

http://www.linuxdevcenter.com/pub/a/linux/2006/11/30/linux-out-of-memory.html

Program A: malloc memory but do reference any data inside the allocated memory (mallocaed but not used):
#include <stdio.h>
#include <stdlib.h>

#define MEGABYTE 1024*1024

int main(int argc, char *argv[])
{
        void *myblock = NULL;
        int count = 0;

        while (1)
        {
                myblock = (void *) malloc(MEGABYTE);
                if (!myblock) break;
                printf("Currently allocating %d MB\n", ++count);
        }
        
        exit(0);
}
Compile the program, run it, and wait for a moment. Sooner or later it will go OOM. Now compile the program B, which allocates huge blocks and fills them with 1:
#include <stdio.h>
#include <stdlib.h>

#define MEGABYTE 1024*1024

int main(int argc, char *argv[])
{
        void *myblock = NULL;
        int count = 0;

        while(1)
        {
                myblock = (void *) malloc(MEGABYTE);
                if (!myblock) break;
                memset(myblock,1, MEGABYTE);
                printf("Currently allocating %d MB\n",++count);
        }
        exit(0);
        
}
Notice the difference? Likely, program A allocates more memory blocks than program B does. It's also obvious that you will see the word "Killed" not too long after executing program B. Both programs end for the same reason: there is no more space available. More specifically, program A ends gracefully because of a failed malloc(). Program B ends because of the Linux kernel's so-called OOM killer.
The first fact to observe is the amount of allocated blocks. Assume that you have 256MB of RAM and 888MB of swap (my current Linux settings). Program B ended at:
Currently allocating 1081 MB
On the other hand, program A ended at:
Currently allocating 3056 MB
Where did A get that extra 1975MB? Did I cheat? Of course not! If you look closer on both listings, you will find out that program B fills the allocated memory space with 1s, while A merely simply allocates without doing anything. This happens because Linux employs deferred page allocation. In other words, allocation doesn't actually happen until the last moment you really use it; for example, by writing data to the block. So, unless you touch the block, you can keep asking for more. The technical term for this is optimistic memory allocation.

Other than free check smem for memory usage

Here is session when each program was run:

|14:59:41|ec2-user@mybox:[tmp]> cat memA.c
#include <stdio.h>
#include <stdlib.h>

#define MEGABYTE 1024*1024

int main(int argc, char *argv[])
{
        void *myblock = NULL;
        int count = 0;

        while (1)
        {
                myblock = (void *) malloc(MEGABYTE);
                if (!myblock) break;
                printf("Currently allocating %d MB\n", ++count);
        }

        exit(0);
}
|14:59:49|ec2-user@mybox:[tmp]> free -tam
             total       used       free     shared    buffers     cached  available
Mem:          7483        349       7134          0         10         63       7098
-/+ buffers/cache:        275       7208
Swap:         8191        741       7450
Total:       15675       1090      14585
|14:59:56|ec2-user@mybox:[tmp]>  grep swap /etc/fstab
/swapfile               swap                    swap    defaults        0 0
|15:00:02|ec2-user@mybox:[tmp]> ls -l /swapfile
-rw-r--r-- 1 root root 8589934592 Nov 17 10:07 /swapfile
|15:00:06|ec2-user@mybox:[tmp]> ./memA
Currently allocating 1 MB
Currently allocating 2 MB
Currently allocating 3 MB
Currently allocating 4 MB
Currently allocating 5 MB
Currently allocating 6 MB
Currently allocating 7 MB

<many lines deleted>

Currently allocating 2495385 MB
Currently allocating 2495386 MB
Currently allocating 2495387 MB
Currently allocating 2495388 MB
Killed
# Simultaneously on another screen get memory stats
|14:54:19|ec2-user@mybox:[~]> while true
> do
> free -tam
> sleep 10
> done
             total       used       free     shared    buffers     cached  available
Mem:          7483        468       7015          0         21        178       7071
-/+ buffers/cache:        268       7215
Swap:         8191        732       7459
Total:       15675       1201      14474
             total       used       free     shared    buffers     cached  available
Mem:          7483       1582       5900          0         21        178       5956
-/+ buffers/cache:       1382       6101
Swap:         8191        732       7459
Total:       15675       2315      13359
             total       used       free     shared    buffers     cached  available
Mem:          7483       4042       3441          0         21        178       3497
-/+ buffers/cache:       3842       3641
Swap:         8191        732       7459
Total:       15675       4775      10900
             total       used       free     shared    buffers     cached  available
Mem:          7483       5800       1683          0         21        178       1739
-/+ buffers/cache:       5599       1883
Swap:         8191        732       7459
Total:       15675       6533       9142
             total       used       free     shared    buffers     cached  available
Mem:          7483       7369        114          0          0          8         55
-/+ buffers/cache:       7360        123
Swap:         8191        766       7425
Total:       15675       8136       7539
             total       used       free     shared    buffers     cached  available
Mem:          7483       7371        112          0          0         15         56
-/+ buffers/cache:       7355        128
Swap:         8191       1967       6224
Total:       15675       9339       6336
             total       used       free     shared    buffers     cached  available
Mem:          7483       7387         96          0          0         16         39
-/+ buffers/cache:       7369        113
Swap:         8191       2969       5222
Total:       15675      10356       5319
             total       used       free     shared    buffers     cached  available
Mem:          7483       7387         95          0          0         16         37
-/+ buffers/cache:       7369        113
Swap:         8191       3963       4228
Total:       15675      11351       4324
             total       used       free     shared    buffers     cached  available
Mem:          7483       7383         99          0          2          9         37
-/+ buffers/cache:       7372        111
Swap:         8191       5037       3154
Total:       15675      12421       3254
             total       used       free     shared    buffers     cached  available
Mem:          7483       7387         95          0          4         12         34
-/+ buffers/cache:       7371        112
Swap:         8191       6197       1994
Total:       15675      13585       2090
             total       used       free     shared    buffers     cached  available
Mem:          7483       7376        107          0          2         12         45
-/+ buffers/cache:       7361        121
Swap:         8191       7267        924
Total:       15675      14644       1031
             total       used       free     shared    buffers     cached  available
Mem:          7483       7387         96          0          1         10         32
-/+ buffers/cache:       7375        108
Swap:         8191       8191          0
Total:       15675      15579         96
             total       used       free     shared    buffers     cached  available
Mem:          7483        424       7059          0          6         34       7006
-/+ buffers/cache:        383       7100
Swap:         8191        743       7448
Total:       15675       1167      14508


#--------------------------------------------------------------------------------------


|15:13:41|ec2-user@mybox:[tmp]> cat memB.c
#include <stdio.h>
#include <stdlib.h>

#define MEGABYTE 1024*1024

int main(int argc, char *argv[])
{
        void *myblock = NULL;
        int count = 0;

        while(1)
        {
                myblock = (void *) malloc(MEGABYTE);
                if (!myblock) break;
                memset(myblock,1, MEGABYTE);
                printf("Currently allocating %d MB\n",++count);
        }
        exit(0);

}


Currently allocating 1 MB
Currently allocating 2 MB
Currently allocating 3 MB
Currently allocating 4 MB
Currently allocating 5 MB
Currently allocating 6 MB
Currently allocating 7 MB

<many lines deleted>

Currently allocating 14380 MB
Currently allocating 14381 MB
Currently allocating 14382 MB
Currently allocating 14383 MB
Currently allocating 14384 MB
Currently allocating 14385 MB
Currently allocating 14386 MB
Currently allocating 14387 MB
Killed

# Simultaneously on another screen get memory stats
|15:12:07|ec2-user@mybox:[~]> while true; do free -tam; sleep 10; done total used free shared buffers cached available Mem: 7483 346 7137 0 13 97 7120 -/+ buffers/cache: 234 7248 Swap: 8191 738 7453 Total: 15675 1085 14590 total used free shared buffers cached available Mem: 7483 7385 98 0 0 17 34 -/+ buffers/cache: 7367 116 Swap: 8191 1982 6209 Total: 15675 9367 6308 total used free shared buffers cached available Mem: 7483 7387 96 0 0 17 32 -/+ buffers/cache: 7368 114 Swap: 8191 2879 5312 Total: 15675 10266 5409 total used free shared buffers cached available Mem: 7483 7384 99 0 1 17 35 -/+ buffers/cache: 7366 117 Swap: 8191 3824 4367 Total: 15675 11208 4466 total used free shared buffers cached available Mem: 7483 7385 98 0 1 13 32 -/+ buffers/cache: 7370 113 Swap: 8191 4753 3438 Total: 15675 12138 3537 total used free shared buffers cached available Mem: 7483 7385 97 0 2 13 32 -/+ buffers/cache: 7369 113 Swap: 8191 5762 2429 Total: 15675 13147 2527 total used free shared buffers cached available Mem: 7483 7387 96 0 2 13 31 -/+ buffers/cache: 7371 112 Swap: 8191 6737 1454 Total: 15675 14124 1551 total used free shared buffers cached available Mem: 7483 7384 99 0 3 14 34 -/+ buffers/cache: 7366 117 Swap: 8191 7663 528 Total: 15675 15047 627 total used free shared buffers cached available Mem: 7483 246 7237 0 4 17 7173 -/+ buffers/cache: 225 7258 Swap: 8191 925 7266 Total: 15675 1171 14503 total used free shared buffers cached available Mem: 7483 316 7167 0 6 35 7115 -/+ buffers/cache: 274 7209 Swap: 8191 749 7442 Total: 15675 1065 14610


[root@mybox tmp]# egrep -i 'oom|Out of memory|killed process' /var/log/messages
Apr 18 14:56:52 ip-172-31-10-191 kernel: [13149384.816317] docker invoked oom-killer: gfp_mask=0x200da, order=0, oom_score_adj=0
Apr 18 14:56:52 ip-172-31-10-191 kernel: [13149384.850184]  [<ffffffff8113a691>] oom_kill_process+0x201/0x360
Apr 18 14:56:52 ip-172-31-10-191 kernel: [13149385.042861] [ pid ]   uid  tgid total_vm      rss nr_ptes swapents oom_score_adj name
Apr 18 14:56:52 ip-172-31-10-191 kernel: [13149385.346663] Out of memory: Kill process 331 (mem) score 932 or sacrifice child
Apr 18 14:56:52 ip-172-31-10-191 kernel: [13149385.349484] Killed process 331 (mem) total-vm:2555698400kB, anon-rss:2379564kB, file-rss:0kB
Apr 18 15:13:41 ip-172-31-10-191 kernel: [13150392.784046] aws invoked oom-killer: gfp_mask=0x200da, order=0, oom_score_adj=0
Apr 18 15:13:41 ip-172-31-10-191 kernel: [13150392.816973]  [<ffffffff8113a691>] oom_kill_process+0x201/0x360
Apr 18 15:13:41 ip-172-31-10-191 kernel: [13150392.998954] [ pid ]   uid  tgid total_vm      rss nr_ptes swapents oom_score_adj name
Apr 18 15:13:41 ip-172-31-10-191 kernel: [13150393.403518] Out of memory: Kill process 7449 (memB) score 923 or sacrifice child
Apr 18 15:13:41 ip-172-31-10-191 kernel: [13150393.406375] Killed process 7449 (memB) total-vm:14853368kB, anon-rss:7235424kB, file-rss:4kB


See also:
1. time yes | tr \\n x | head -c $((1024*1024*1024*1)) | grep n # Allocated 1 GB 2. https://github.com/julman99/eatmemory/blob/master/eatmemory.c
3. Python
#!/usr/bin/env python

import sys
import time

if len(sys.argv) != 2:
    print "usage: fillmem <number-of-megabytes>"
    sys.exit()

count = int(sys.argv[1])

megabyte = (0,) * (1024 * 1024 / 8)

data = megabyte * count

while True:

    time.sleep(1)


No comments:

Post a Comment