使用 dd 检查存储性能

[ad_1]

本文包含一些示例命令,向您展示如何使用 dd 命令粗略估计硬盘驱动器和 RAID 阵列的性能。 准确的测量必须考虑到诸如 写放大系统调用开销,本指南没有。 对于可能提供更准确结果的工具,您可能需要考虑使用 .

为了解决与文件系统相关的性能问题,这些示例展示了如何通过直接读写驱动器和阵列的块设备来测试块级别的驱动器和阵列的性能。 警告:写测试将破坏运行它们的块设备上的任何数据。 不要在任何包含您要保留的数据的设备上运行它们!

四项测试

以下是四个可用于测试块设备性能的示例 dd 命令:

  1. 从 $MY_DISK 读取的一个进程:
    # dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache
  2. 写入 $MY_DISK 的一个进程:
    # dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct
  3. 两个进程同时从 $MY_DISK 读取:
    # (dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache &); (dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache skip=200 &)
  4. 两个进程同时写入 $MY_DISK:
    # (dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct &); (dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct skip=200 &)

– iflag=nocache 和 oflag=direct 参数在(分别)执行读写测试时很重要,因为如果没有它们,dd 命令有时会显示数据传入/传出的最终速度 内存 而不是硬盘。

– bs 和 count 参数的值有些随意,我选择的值应该足够大,以便在大多数情况下为当前硬件提供不错的平均值。

– 空和零设备用于读写测试中的目标和源(分别),因为它们足够快,不会成为性能测试中的限制因素。

– 并发读写测试中第二条dd命令的skip=200参数是为了保证dd的两个副本在硬盘的不同区域运行。

16个例子

下面的演示显示了对以下四个块设备中的每一个运行上述四个测试中的每一个的结果:

  1. MY_DISK=/dev/sda2(在示例 1-X 中使用)
  2. MY_DISK=/dev/sdb2(在示例 2-X 中使用)
  3. MY_DISK=/dev/md/stripped(在示例 3-X 中使用)
  4. MY_DISK=/dev/md/mirrored(在示例 4-X 中使用)

本指南末尾提供了在 PC 上运行这些测试的视频演示。

首先将您的计算机置于救援模式,以减少来自后台服务的磁盘 I/O 可能随机影响您的测试结果的机会。 警告:这将关闭所有非必要的程序和服务。 在运行这些命令之前,请务必保存您的工作。 您需要知道您的 root 密码才能进入救援模式。 passwd 命令以 root 用户身份运行时,将提示您(重新)设置您的 root 帐户密码。

$ sudo -i
# passwd
# setenforce 0
# systemctl rescue

您可能还想暂时禁用日志记录到磁盘:

# sed -r -i.bak 's/^#?Storage=.*/Storage=none/' /etc/systemd/journald.conf
# systemctl restart systemd-journald.service

如果您有交换设备,可以暂时禁用它并用于执行以下测试:

# swapoff -a
# MY_DEVS=$(mdadm --detail /dev/md/swap | grep active | grep -o "/dev/sd.*")
# mdadm --stop /dev/md/swap
# mdadm --zero-superblock $MY_DEVS

示例 1-1(从 sda 读取)

# MY_DISK=$(echo $MY_DEVS | cut -d ' ' -f 1)
# dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 1.7003 s, 123 MB/s

示例 1-2(写入 sda)

# MY_DISK=$(echo $MY_DEVS | cut -d ' ' -f 1)
# dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 1.67117 s, 125 MB/s

示例 1-3(从 sda 并发读取)

# MY_DISK=$(echo $MY_DEVS | cut -d ' ' -f 1)
# (dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache &); (dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache skip=200 &)
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 3.42875 s, 61.2 MB/s
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 3.52614 s, 59.5 MB/s

示例 1-4(并发写入 sda)

# MY_DISK=$(echo $MY_DEVS | cut -d ' ' -f 1)
# (dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct &); (dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct seek=200 &)
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 3.2435 s, 64.7 MB/s
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 3.60872 s, 58.1 MB/s

示例 2-1(从 sdb 读取)

# MY_DISK=$(echo $MY_DEVS | cut -d ' ' -f 2)
# dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 1.67285 s, 125 MB/s

示例 2-2(写入 sdb)

# MY_DISK=$(echo $MY_DEVS | cut -d ' ' -f 2)
# dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 1.67198 s, 125 MB/s

示例 2-3(从 sdb 并发读取)

# MY_DISK=$(echo $MY_DEVS | cut -d ' ' -f 2)
# (dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache &); (dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache skip=200 &)
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 3.52808 s, 59.4 MB/s
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 3.57736 s, 58.6 MB/s

例2-4(并发写入sdb)

# MY_DISK=$(echo $MY_DEVS | cut -d ' ' -f 2)
# (dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct &); (dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct seek=200 &)
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 3.7841 s, 55.4 MB/s
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 3.81475 s, 55.0 MB/s

示例 3-1(从 RAID0 读取)

# mdadm --create /dev/md/stripped --homehost=any --metadata=1.0 --level=0 --raid-devices=2 $MY_DEVS
# MY_DISK=/dev/md/stripped
# dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 0.837419 s, 250 MB/s

示例 3-2(写入 RAID0)

# MY_DISK=/dev/md/stripped
# dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 0.823648 s, 255 MB/s

示例 3-3(从 RAID0 并发读取)

# MY_DISK=/dev/md/stripped
# (dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache &); (dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache skip=200 &)
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 1.31025 s, 160 MB/s
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 1.80016 s, 116 MB/s

示例 3-4(并发写入 RAID0)

# MY_DISK=/dev/md/stripped
# (dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct &); (dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct seek=200 &)
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 1.65026 s, 127 MB/s
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 1.81323 s, 116 MB/s

示例 4-1(从 RAID1 读取)

# mdadm --stop /dev/md/stripped
# mdadm --create /dev/md/mirrored --homehost=any --metadata=1.0 --level=1 --raid-devices=2 --assume-clean $MY_DEVS
# MY_DISK=/dev/md/mirrored
# dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 1.74963 s, 120 MB/s

示例 4-2(写入 RAID1)

# MY_DISK=/dev/md/mirrored
# dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 1.74625 s, 120 MB/s

示例 4-3(从 RAID1 并发读取)

# MY_DISK=/dev/md/mirrored
# (dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache &); (dd if=$MY_DISK of=/dev/null bs=1MiB count=200 iflag=nocache skip=200 &)
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 1.67171 s, 125 MB/s
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 1.67685 s, 125 MB/s

示例 4-4(并发写入 RAID1)

# MY_DISK=/dev/md/mirrored
# (dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct &); (dd if=/dev/zero of=$MY_DISK bs=1MiB count=200 oflag=direct seek=200 &)
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 4.09666 s, 51.2 MB/s
200+0 records in
200+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 4.1067 s, 51.1 MB/s

恢复您的交换设备和日志配置

# mdadm --stop /dev/md/stripped /dev/md/mirrored
# mdadm --create /dev/md/swap --homehost=any --metadata=1.0 --level=1 --raid-devices=2 $MY_DEVS
# mkswap /dev/md/swap
# swapon -a
# mv /etc/systemd/journald.conf.bak /etc/systemd/journald.conf
# systemctl restart systemd-journald.service
# reboot

解释结果

示例 1-1、1-2、2-1 和 2-2 显示我的每个驱动器的读写速度约为 125 MB/s。

示例 1-3、1-4、2-3 和 2-4 表明,当在同一驱动器上并行执行两次读取或两次写入时,每个进程获得的带宽约为驱动器带宽的一半 (60 MB/s)。

3-x 示例显示了将两个驱动器放在 RAID0(数据剥离)阵列中的性能优势。 在所有情况下,这些数字表明 RAID0 阵列的执行速度大约是任一驱动器能够独立执行的速度的两倍。 权衡是您丢失所有内容的可能性是其两倍,因为每个驱动器仅包含一半的数据。 三驱动器阵列的执行速度是单个驱动器的三倍(所有驱动器都相同),但遭受故障的可能性是其三倍 灾难性故障.

4-x 示例表明,RAID1(数据镜像)阵列的性能与单个磁盘的性能相似,除了多个进程同时读取的情况(示例 4-3)。 在多进程读取的情况下,RAID1阵列的性能与RAID0阵列相似。 这意味着您将看到 RAID1 的性能优势,但仅限于进程并发读取时。 例如,当您尝试在前台使用 Web 浏览器或电子邮件客户端时,如果某个进程尝试在后台访问大量文件。 RAID1 的主要好处是您的数据不太可能丢失 如果驱动器出现故障.

视频演示

使用 dd 测试存储吞吐量

故障排除

如果上述测试未按预期执行,则可能是驱动器损坏或出现故障。 大多数现代硬盘驱动器都具有内置的自我监控、分析和报告技术(聪明的)。 如果您的驱动器支持它,则可以使用 smartctl 命令查询您的硬盘驱动器的内部统计信息:

# smartctl --health /dev/sda
# smartctl --log=error /dev/sda
# smartctl -x /dev/sda

您可以调整 PC 以获得更好性能的另一种方法是更改​​您的 PC I/O 调度器. Linux 系统支持多个 I/O 调度程序和当前默认的 Fedora 系统是 多队列 的变种 最后期限 调度程序。 默认的整体性能非常好,并且对于具有许多处理器和大型磁盘阵列的大型服务器来说非常好。 但是,有一些更专业的调度程序在某些情况下可能会表现得更好。

要查看您的驱动器正在使用哪个 I/O 调度程序,请发出以下命令:

$ for i in /sys/block/sd?/queue/scheduler; do echo "$i: $(<$i)"; done

您可以通过将所需调度程序的名称写入 /sys/block//queue/scheduler 文件来更改驱动器的调度程序:

# echo bfq > /sys/block/sda/queue/scheduler

您可以通过创建一个永久更改 udev 规则 为您的驱动器。 下面的例子展示了如何创建一个 udev 规则来设置所有 旋转驱动 使用 BFQ I/O 调度器:

# cat << END > /etc/udev/rules.d/60-ioscheduler-rotational.rules
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="1", ATTR{queue/scheduler}="bfq"
END

这是另一个设置所有的示例 固态驱动器 使用 NOOP I/O 调度器:

# cat << END > /etc/udev/rules.d/60-ioscheduler-solid-state.rules
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="none"
END

更改 I/O 调度程序不会影响设备的原始吞吐量,但通过将前台任务的带宽优先于后台任务或消除不必要的块重新排序,可能会使您的 PC 看起来响应更快。

拍摄者 詹姆斯·多诺万不飞溅.

[ad_2]

Related Posts