はじめに
みなさん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のメモリ管理はまた別の記事にしようと思いますので、ここでは指定した数値によってメモリ使用率が自由に指定できることがわかれば十分でしょう。
まとめ
これでインフラエンジニアとして自由にメモリ負荷をかけることができるようになりました。
先に述べたようにリソース監視のテストなどで、メモリ使用率を上げてテストしたいときはよくありますので、これを参考にどんどんテストしていきましょう。
おまけ
複数同時に動かすこともできます。
さっきは1つのプロセスで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