【Linux】メモリ負荷プログラム

# はじめに
**みなさんLinuxでメモリの負荷テストしてますか？**

システムの性能・負荷テストでメモリの負荷をかけたいときはよくありますよね。

CPUの場合は適当にスクリプトでも何でもループさせればすぐにCPU100%になりますが、メモリの場合はそうもいきません。
とはいえ、サーバのスペックどおりアプリケーションが動作するかどうか、インフラ観点でテストできないのも、もどかしいですよね？

あと、インフラのテストとしてメモリ使用率のリソース監視が正常に動いているか確認したいのに、一時的に閾値を下げてテストしている様子をよく見かけます。

どうすればインフラエンジニアとしてスマートにメモリ負荷をかけられるのでしょうか？

という疑問を記事にしました。

# メモリを使うとは？
これはもう実際試したほうがわかりやすいと思いますので、試していきましょう。

## メモリ負荷プログラム準備


```
# vi mem.c
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
        char *mem;
        int size = atoi(argv[1]);　★プログラムの引数でメモリサイズ指定
        int mb = 1024 * 1024;　　　★MByteに掛け算
        int memsize = size * mb;
        mem = (char *)malloc(memsize);　★動的メモリ確保
        if ( NULL == mem ) {
                perror("Can't malloc");
                exit(1);
        }

        printf("memsize=%d\n",memsize);

        int j = 0;
        for(j=0; j<4; j++){
            int i = 0;
            for(i=0; i<memsize; i++){
                mem[i] = 0xFF;　　　　★メモリアクセス
                mem[i] = 0x00;　　　　★メモリアクセス
            }
        }
}
# cc -o mem mem.c
# ls 
mem mem.c
※Cコンパイラのccコマンドでコンパイルします。
※gccがインストールされてない場合、yum -y install gccでインストールしてください。
※「mem」が実行ファイルです。
```

## メモリ負荷プログラム実行

### 1GByteの場合
```
# ./mem 1024
memsize=1073741824　　★1024×1024×1024byte(1Gbyte)のメモリサイズ
# top
top - 22:43:36 up  1:11,  2 users,  load average: 0.29, 0.11, 0.08
Tasks: 112 total,   2 running, 110 sleeping,   0 stopped,   0 zombie
%Cpu(s): 48.1 us,  2.0 sy,  0.0 ni, 49.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1862996 total,   454676 free,  1247804 used,   160516 buff/cache
KiB Swap:  2097148 total,  2097148 free,        0 used.   463896 avail Mem

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
  1964 root      20   0 1052796   1.0g    412 R 100.0 56.3   0:07.44 mem
     1 root      20   0  128016   6564   4060 S   0.0  0.4   0:02.36 systemd
     2 root      20   0       0      0      0 S   0.0  0.0   0:00.02 kthreadd
     4 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H
     6 root      20   0       0      0      0 S   0.0  0.0   0:00.26 ksoftirqd/0
     7 root      rt   0       0      0      0 S   0.0  0.0   0:00.06 migration/0
     8 root      20   0       0      0      0 S   0.0  0.0   0:00.00 rcu_bh
```
「RES」のところが指定したとおり「1.0g」となっているので、物理メモリ1Gbyteがちゃんと使えてますね。


### 2GByteの場合
次はためしに2Gbyteのメモリを使用してみましょう。

```
# ./mem 2048
Can't malloc: Cannot allocate memory
```
あれ、何かエラーが出てしまいました。

```
# free
              total        used        free      shared  buff/cache   available
Mem:        1862996      196696     1505760        9764      160540     1515004
Swap:       2097148           0     2097148
```

メモリが少し足りないのでしょうか。
少し数値を下げてみましょう。


```
# ./mem 2000
memsize=2097152000

top - 22:52:17 up  1:20,  2 users,  load average: 0.44, 0.16, 0.10
Tasks: 113 total,   3 running, 110 sleeping,   0 stopped,   0 zombie
%Cpu(s): 12.7 us, 48.5 sy,  0.0 ni, 27.7 id,  5.3 wa,  0.0 hi,  5.8 si,  0.0 st
KiB Mem :  1862996 total,    75448 free,  1763408 used,    24140 buff/cache
KiB Swap:  2097148 total,  1382652 free,   714496 used.    11892 avail Mem

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
  2014 root      20   0 2052220   1.4g     68 R  80.4 76.1   0:21.47 mem
    33 root      20   0       0      0      0 S  44.9  0.0   0:03.78 kswapd0
     9 root      20   0       0      0      0 R   0.7  0.0   0:01.42 rcu_sched
   656 root      20   0  273260    712    332 S   0.3  0.0   0:13.40 vmtoolsd
  1034 root      20   0  574284    944    480 S   0.3  0.1   0:01.70 tuned
  1038 root      20   0  222740   1928   1692 S   0.3  0.1   0:00.94 rsyslogd
  1291 postfix   20   0   89892    104    104 S   0.3  0.0   0:00.05 pickup
  1903 root      20   0       0      0      0 S   0.3  0.0   0:01.96 kworker/0:1
```

今度はうまく実行できました。
ただ、「RES」の値を見ると少し足りないですね。指定した値は2G弱くらいのはずですが、「RES」の値は1.4g程度です。

なぜ、少し足りないのでしょうか？

「kswapd」というプロセスが「mem」プログラムの下に表示されてるのが見えると思います。
そうですね。「kswapd」プロセスが動いているのでスワップが動いていました。

Linuxのメモリ管理はまた別の記事にしようと思いますので、ここでは指定した数値によってメモリ使用率が自由に指定できることがわかれば十分でしょう。

# まとめ
これでインフラエンジニアとして自由にメモリ負荷をかけることができるようになりました。
先に述べたようにリソース監視のテストなどで、メモリ使用率を上げてテストしたいときはよくありますので、これを参考にどんどんテストしていきましょう。


## おまけ
複数同時に動かすこともできます。
さっきは１つのプロセスで2Gbyte指定してたものはアロケートエラーでしたが、以下では500M弱を5本実行してもアロケートエラーが出てないのが不思議ですね。

```
# ./mem 500&
[2] 2018
memsize=524288000
# ./mem 500&
[3] 2019
memsize=524288000
# ./mem 500&
[4] 2020
memsize=524288000
# ./mem 500&
[5] 2021
memsize=524288000
# ./mem 500&
[6] 2022
memsize=524288000
# ./mem 500&
[7] 2023
memsize=524288000
top - 22:58:25 up  1:26,  2 users,  load average: 6.22, 2.21, 0.90
Tasks: 120 total,  10 running, 110 sleeping,   0 stopped,   0 zombie
%Cpu(s):  9.7 us, 60.5 sy,  0.0 ni,  0.0 id,  0.3 wa,  0.0 hi, 29.4 si,  0.0 st
KiB Mem :  1862996 total,    52428 free,  1787960 used,    22608 buff/cache
KiB Swap:  2097148 total,       96 free,  2097052 used.     7412 avail Mem

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
    33 root      20   0       0      0      0 R  28.1  0.0   1:36.49 kswapd0
  2018 root      20   0  516220 230876     36 R  24.5 12.4   0:18.87 mem
  2019 root      20   0  516220 224784     36 R  24.5 12.1   0:19.22 mem
  2023 root      20   0  516220 236852     36 R  24.2 12.7   0:17.97 mem
  2017 root      20   0  516220 229944     36 R  23.9 12.3   0:22.20 mem
  2020 root      20   0  516220 217728     36 R  23.9 11.7   0:19.23 mem
  2021 root      20   0  516220 200428     36 R  23.2 10.8   0:18.29 mem
  2022 root      20   0  516220 230704     36 R  23.2 12.4   0:17.86 mem
     9 root      20   0       0      0      0 R   0.3  0.0   0:02.62 rcu_sched
   656 root      20   0  273260   1436   1132 S   0.3  0.1   0:14.68 vmtoolsd
     1 root      20   0  128016    784    784 S   0.0  0.0   0:02.46 systemd
     2 root      20   0       0      0      0 S   0.0  0.0   0:00.02 kthreadd
     4 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H
```