swap
swap ,内存交换空间,它是磁盘上的一块空间,主要作用是为了防止物理内存不足。
CPU 从内存中读取数据。当内存的空间不足时, CPU 难以读取到数据,导致程序无法正常工作。所以诞生了 swap 内存交换空间,系统将内存中不常用的程序和数据放到 swap 中,从而给内存腾出空间,使得内存可以读取更多的数据,保证程序的顺利运行。
swap 构建
构建 swap 步骤:
1. 创建磁盘分区;
2. mkswap 构建 swap;
3. swapon 启动 swap;
1. 创建磁盘分区
fdisk 命令创一个新分区:
[root@test test]# fdisk /dev/sdb
The device presents a logical sector size that is smaller than
the physical sector size. Aligning to a physical sector (or optimal
I/O) size boundary is recommended, or performance may be impacted.
Welcome to fdisk (util-linux 2.23.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): n
Partition type:
p primary (1 primary, 0 extended, 3 free)
e extended
Select (default p): p
Partition number (2-4, default 2):
No free sectors available
显示分区创建失败,No free sectors available.
使用 101 介绍的 LVM 方式创一个 LV test:
[root@test test]# lvdisplay | grep test
LV Path /dev/lianhuasheng/test
LV Name test
2. mkswap 构建 swap:
[root@test test]# free
total used free shared buff/cache available
Mem: 65692228 56611752 631264 56492 8449212 7650528
Swap: 0 0 0
[root@test test]# mkswap /dev/lianhuasheng/test
mkswap: /dev/lianhuasheng/test: warning: wiping old ext4 signature.
Setting up swapspace version 1, size = 204796 KiB
no label, UUID=2ed9b70d-b267-4c26-9159-1bfb273c7d7c
[root@test test]# free
total used free shared buff/cache available
Mem: 65692228 56359176 1139968 56492 8193084 7902468
Swap: 0 0 0
这里,构建 swap 是不需要 mount point 的,因为是系统自动将内存数据写入 swap 中的。
3. swapon 启动 swap:
[root@test test]# free -h
total used free shared buff/cache available
Mem: 62G 54G 511M 55M 7.9G 7.0G
Swap: 0B 0B 0B
[root@test test]# swapon /dev/lianhuasheng/test
[root@test test]# free -h
total used free shared buff/cache available
Mem: 62G 54G 941M 55M 7.7G 7.2G
Swap: 199M 0B 199M
swap 构建成功。
如果系统没有配置 LVM 并且磁盘分区也分不了的话,可以使用 dd 命令构建一个文件,然后对此文件构建 swap:
[root@test lianhuasheng]# dd if=/dev/zero of=/root/lianhuasheng/swap/lianhuasheng.swap bs=1M count=512
512+0 records in
512+0 records out
536870912 bytes (537 MB) copied, 0.356955 s, 1.5 GB/s
[root@test swap]# ll -h lianhuasheng.swap
-rw-r--r--. 1 root root 512M Apr 1 00:12 lianhuasheng.swap
[root@test swap]# mkswap lianhuasheng.swap
Setting up swapspace version 1, size = 524284 KiB
no label, UUID=510ba316-c6e5-4993-b616-e72969cd6322
[root@test swap]# free -h
total used free shared buff/cache available
Mem: 62G 53G 663M 47M 8.0G 7.3G
Swap: 199M 199M 16K
[root@test swap]# swapon lianhuasheng.swap
swapon: /root/lianhuasheng/swap/lianhuasheng.swap: insecure permissions 0644, 0600 suggested.
[root@test swap]# free -h
total used free shared buff/cache available
Mem: 62G 54G 304M 47M 8.1G 7.1G
Swap: 711M 200M 511M
使用 swapoff 命令卸载 swap:
[root@test swap]# swapoff /dev/lianhuashengl/test
[root@test swap]# free -h
total used free shared buff/cache available
Mem: 62G 53G 761M 54M 8.0G 7.4G
Swap: 511M 511M 60K
[root@test swap]# swapoff lianhuasheng.swap
[root@test swap]# free -h
total used free shared buff/cache available
Mem: 62G 54G 888M 55M 7.6G 7.1G
Swap: 0B 0B 0B
磁盘性能
前面使用 dd 构建 swap 时,出现以下提示信息:
[root@test lianhuasheng]# dd if=/dev/zero of=/root/lianhuasheng/swap/lianhuasheng.swap bs=1M count=512
512+0 records in
512+0 records out
536870912 bytes (537 MB) copied, 0.356955 s, 1.5 GB/s
有必要重点介绍这段,这是 dd 在写入文件到磁盘。
其中,/dev/zero 是伪设备,它会产生空字符流,不会有 IO,然后将空字符写到 of 指定的文件中,在这时会有 IO。所以这个命令可用来测试磁盘的写能力。即,上面打印信息的意思是每秒写入 1.5GB 的数据到磁盘中。
既然有测试磁盘写能力的,就有测试磁盘读能力的 dd。
/dev/null 可以被用来测试磁盘的读能力。它是一个回收站,文件放到这里不产生 IO。例如:
[root@test swap]# dd if=lianhuasheng.swap of=/dev/null bs=1M
512+0 records in
512+0 records out
536870912 bytes (537 MB) copied, 1.07563 s, 499 MB/s
系统每秒读 499MB 的数据到 /dev/null 中,总共花了 1.07563s。
如果将 if 指定为磁盘,of 指定为文件,就可以测试磁盘的读写性能。例如:
[root@test swap]# dd if=/dev/sda2 of=disk bs=1K
^C2729809+0 records in
2729808+0 records out
2795323392 bytes (2.8 GB) copied, 11.4058 s, 245 MB/s
系统每秒从 sda2 中读写 245MB 数据到文件 disk 。
这里测试的磁盘读写性能都是有内存缓存的,即数据并不完全从磁盘中读写,也有部分数据是从内存中读写的。指定 dd 的 oflag 为 direct模式可在读数据的时候跳过内存缓存,指定 iflag 为 direct 模式将写请求封装成 I/O 指令直接发到磁盘,而非 direct 模式是把数据写入到系统缓存就认为 I/O 成功了。
测试磁盘纯读性能:
[root@test swap]# dd if=lianhuasheng.swap of=/dev/null bs=1M iflag=direct
512+0 records in
512+0 records out
536870912 bytes (537 MB) copied, 1.7492 s, 307 MB/s
测试磁盘纯写性能:
[root@test swap]# dd if=/dev/zero of=lianhuasheng.swap bs=1M count=1024 oflag=direct
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 2.5872 s, 415 MB/s
测试磁盘纯读写性能:
[root@test swap]# dd if=/dev/sda2 of=disk bs=1K iflag=direct oflag=direct
^C328136+0 records in
328135+0 records out
336010240 bytes (336 MB) copied, 93.313 s, 3.6 MB/s
在使用 direct 模式之前,可先清除内存缓存:
sync && echo 3 > /proc/sys/vm/drop_caches
其中,命令 sync 用于数据同步。系统在写入数据到磁盘时,会先写到内存的 buffer 中。通过 sync 命令将 buffer 中的数据强制写入到磁盘中。
echo 3 表示清除内存中的页面缓存(page cache),目录项和 inode 节点。类似的还有 echo 1 表示清除页面缓存,echo 2 表示清除目录项和 inode。
清除内存缓存,测试文件的读性能:
[root@test swap]# free -h
total used free shared buff/cache available
Mem: 62G 56G 1.0G 55M 5.0G 4.8G
Swap: 0B 0B 0B
[root@test swap]# sync && echo 3 > /proc/sys/vm/drop_caches
[root@test swap]# free -h
total used free shared buff/cache available
Mem: 62G 54G 7.3G 55M 901M 7.2G
Swap: 0B 0B 0B
[root@test swap]# dd if=lianhuasheng.swap of=/dev/null bs=1M iflag=direct
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 3.54052 s, 303 MB/s
[root@test swap]# dd if=lianhuasheng.swap of=/dev/null bs=1M iflag=direct
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 3.49309 s, 307 MB/s
根据上面的测试结果给磁盘的读写速度排个序: 磁盘读写速度 > 磁盘纯读写速度 ~= 清除内存缓存的纯读写速度。
使用 dd 命令测试磁盘读写性能比较通用,但不专业。专业的测试磁盘工具是 hdparm , 它被用来测试磁盘的读取性能。例如:
[root@test test]# hdparm -t /dev/sda2
/dev/sda2:
Timing buffered disk reads: 1334 MB in 3.00 seconds = 444.43 MB/sec
[root@test test]# hdparm -T /dev/sda2
/dev/sda2:
Timing cached reads: 17748 MB in 2.00 seconds = 8888.37 MB/sec
上面的命令中,-t 表示读取磁盘数据,-T 表示读取内存缓存数据。
内存和磁盘| buffer cache 和 page cache
测试磁盘性能的结果表明:数据读写到磁盘和读写到内存的速度是不一样的。
由于不同硬件的规格,性能的限制,导致硬件的读写速率不一样。数据读写到内存要比读写到磁盘快的多,如果数据直接在内存和磁盘间传输将会慢很多。
想象一下,内存要读 100M 数据,内存的读写速度是 100M/s,而磁盘的读写速度是 50M/s,这时候内存读取 100M 数据将花费 2s 的时间。因为数据传递是连续的,在硬盘向内存传递数据的过程中,内存是不能做其它事情的,只能等待,即原本内存 1s 就能读完的数据却要多花 1s 去等。同样的,在写数据到磁盘时,内存 1s 就能将数据传给磁盘,而磁盘却需要 2s 去写入,内存又要浪费 1s 去等待磁盘写入。因此,这种方式很不合理,为了改善这种情况,buffer cache 和 page cache 的概念就被引入进来。
buff cache:当内存写数据到磁盘时,一部分数据被放到内存中的 buffer cache 里,当系统空间或者 buffer cache 达到一定值时再写入到磁盘。这样内存就可以以很快的速度写数据到 buffer cache,磁盘也可以以较慢的速度从 buffer cache 中读数据。要注意,buffer cache 中的数据并不是即时的,并且缓存在 buffer cache 中的数据遇系统故障或者断电时很有可能会丢失,这时候执行 sync 命令就很有必要了,它会把 buffer cache 中的数据写入到磁盘。
page cache:当数据从磁盘读到内存时,一部分数据会被放到内存中的 page cache 里,这样内存就可以以很快的速度从 page cache 里读数据了,磁盘也可以以较慢的速度往 page cache 里写数据。
buff cache 和 page cache 的示意图如下所示:
注意,buff cache 和 page cache 是内存中的缓冲和缓存,它们和 CPU 内部的 L1/L2 cache 是不一样的!
使用 free 命令查看 buff 和 cache:
[root@test test]# free -wh
total used free shared buffers cache available
Mem: 31G 8.9G 10G 1.6G 326M 11G 20G
Swap: 511M 371M 140M
total 表示总内存;
used 表示已经使用的内存;
free 表示空间内存;
shared 表示进程间的共享内存;
buffers 表示 buffer 缓冲的内存;
cache 表示缓存的内存;
available 表示应用程序可以使用的内存,它包括缓存在内。
公式: total = used + free + buffers + cache。
如果进一步查看 free 的 man 文档会发现文档里有大量的 /proc/meminfo 字段,如:
buffers
Memory used by kernel buffers (Buffers in /proc/meminfo)
cache
Memory used by the page cache and slabs (Cached and Slab in /proc/meminfo)
Liunx 中一切皆文件,/proc 是一个伪文件系统,它是内核状态和统计信息的接口,它有一个配置接口 /proc/sys,可指定一个值更改到该文件系统下的某个文件来修改内核的某个功能或配置。
有两种即时修改 /proc/sys 文件配置的方式:
1. sysctl: sysctl -w var=value,将内核参数 var 修改为给定值 value;
2. echo "value" > /proc/sys/.../...;将给定值 value 写入到文件 /proc/sys/.../... 中。
前面将值 3 写入到文件 /proc/sys/vm/drop_caches 就是用的第二种内核配置文件修改方式来实现清除内存缓存功能的。
(完)