はじめに (対象読者・この記事でわかること)
この記事は、Linuxシステム管理者やサーバー運用に携わる方、大規模なファイル転送が必要な開発者を対象にしています。特に、マルチユーザー環境やリソースが限られたシステムでファイルコピー時のI/O負荷を低く保ちたい方に最適です。
この記事を読むことで、CFQ(Completely Fair Queuing)I/Oスケジューラを使用せずに、Linuxシステムで低負荷で効率的なファイルコピーを実現する具体的な方法を学べます。I/Oスケジューラの変更方法、ファイルコピーコマンドの最適化、I/O優先度の調整といった実践的なテクニックを習得し、システム全体のパフォーマンスを維持しながらファイル転送を行えるようになります。
前提知識
この記事を読み進める上で、以下の知識があるとスムーズです。 - Linuxの基本的なコマンド操作 - ファイルシステムの基本的な理解 - I/Oスケジューラの概念(基本的な理解)
CFQとI/Oスケジューラの概要
Linuxシステムでは、I/Oリクエストを効率的に処理するためにI/Oスケジューラが使用されます。CFQ(Completely Fair Queuing)は、Linuxカーネルで長らくデフォルトとして使用されてきたI/Oスケジューラで、プロセスごとにI/O帯域を公平に分配する特徴があります。
しかし、CFQはプロセス間での公平性を重視するため、大規模なファイルコピーなどの単一の大量I/O操作では、他のプロセスのI/Oリクエストを待たせることでパフォーマンスが低下することがあります。特に、マルチユーザーやマルチタスク環境では、ファイルコピー操作がシステム全体のパフォーマンスに影響を与える可能性があります。
この問題を解決するためには、CFQ以外のI/Oスケジューラを使用するか、ファイルコピー時にI/O優先度を適切に設定する必要があります。以下では、具体的な方法を詳しく解説します。
低負荷ファイルコピーの具体的な方法
ステップ1:I/Oスケジューラの確認と変更
まず、現在システムで使用しているI/Oスケジューラを確認し、必要に応じて変更します。
現在使用中のI/Oスケジューラの確認
Bashcat /sys/block/sda/queue/scheduler
このコマンドを実行すると、現在有効になっているI/Oスケジューラが表示されます。デフォルトでは[cfq]のように表示されることが多いです。
I/Oスケジューラの変更
CFQ以外のスケジューラに変更するには、以下のコマンドを使用します。ここでは、deadlineスケジューラに変更する例を示します。
Bashecho deadline > /sys/block/sda/queue/scheduler
変更後、再度確認コマンドを実行して変更が反映されていることを確認してください。
各スケジューラの特徴と適した使用場面
-
noop: - 特徴: シンプルなFIFO(先入れ先出し)方式で、CPUのオーバーヘッドが少ない - 適した場面: 仮想化環境やストレージが自身でI/Oスケジューリングを行う場合
-
deadline: - 特徴: リクエストの期限を設定し、それを守ることを優先 - 適した場面: ランダムなI/Oが多く、リアルタイム性が求められる環境
-
none: - 特徴: カーネルによるI/Oスケジューリングを完全に無効化 - 適した場面: ストレージデバイスが自身で高度なスケジューリングを行う場合
-
mq-deadline: - 特徴: deadlineのマルチキュー版で、SSDなどの高性能ストレージ向け - 適した場面: NVMe SSDや高速なSATA SSDを使用するシステム
ファイルコピーのような大量連続I/Oでは、deadlineやnoopがCFQよりもパフォーマンスが良い傾向にあります。ただし、システム全体のワークロードに合わせて最適なスケジューラを選択することが重要です。
ステップ2:ファイルコピーコマンドの最適化
I/Oスケジューラの変更に加え、ファイルコピーコマンド自体を最適化することで、さらに低負荷なコピーを実現できます。
rsyncコマンドの最適化オプション
rsyncは、差分転送やファイル属性の保持など多くの機能を持つ強力なファイルコピーツールです。以下のオプションを組み合わせることで、パフォーマンスを向上させることができます。
Bashrsync -aAXv --partial --progress --bwlimit=1000 /source/directory/ /destination/directory/
主なオプションの説明:
- -a: アーカイブモード(-rlptgoDの組み合わせ)
- -A: ACLを保持
- -X: 拡張属性を保持
- -v: 詳細表示
- --partial: 中断された転送を再開可能な状態で保持
- --progress: 転送進捗を表示
- --bwlimit: 転送速度を制限(KB単位、例: 1000=1MB/s)
特に--bwlimitオプションは、I/O負荷を制限するのに有効です。システムの負荷状況に応じて適切な値を設定してください。
cpコマンドのバッファサイズ調整
標準のcpコマンドでも、いくつかのオプションでパフォーマンスを向上させることができます。
Bashcp -a --sparse=always /source/file /destination/file
主なオプションの説明:
- -a: ディレクトリ構造やファイル属性を保持
- --sparse=always: ゼロ埋めめファイルをスパースファイルとして保存(ディスクスペース節約)
さらに、GNU coreutilsに含まれるpv(Pipe Viewer)と組み合わせることで、進捗表示と帯域制限が可能です。
Bashpv /source/file | dd of=/destination/file bs=4M
bsオプションでI/Oブロックサイズを指定し、ストレージの特性に合わせて調整します。一般的には4M〜8M程度が良いでしょう。
複数ファイルの効率的なコピー方法
大量のファイルをコピーする場合、単純に一つずつコピーするよりも、アーカイブしてから転送する方が効率的です。
Bashtar -cf - /source/directory | pv | tar -xf - -C /destination/
この方法では、ファイルシステムのメタデータ(ファイル名、パーミッションなど)のI/Oを一度に処理できるため、多数の小さなファイルをコピーする際に特に有効です。
ステップ3:I/O優先度の調整
I/Oスケジューラの変更に加え、特定のプロセスに対してI/O優先度を設定することで、さらに低負荷なファイルコピーを実現できます。
ioniceコマンドの使い方
ioniceコマンドを使用すると、プロセスのI/O優先度を設定できます。以下に基本的な使用例を示します。
Bashionice -c 3 -p $(pgrep rsync)
主なオプションの説明:
- -c 3: I/Oスケジューリングクラスを「アイドル」に設定(システムがアイドル状態のときのみI/Oを実行)
- -p: プロセスIDを指定
ioniceは3つのクラスをサポートしています:
- クラス0(リアルタイム): 最高の優先度
- クラス1(ベストエフォート): デフォルトの優先度
- クラス2(ベストエフォート): 低優先度
- クラス3(アイドル): システムがアイドル状態のときのみ実行
ファイルコピーのようなバックグラウンド処理では、クラス2またはクラス3を指定することで、システム全体のパフォーマンスへの影響を最小限に抑えられます。
プロセスごとのI/O優先度設定
ファイルコピーコマンドを直接実行する際に、I/O優先度を指定することもできます。
Bashionice -c 3 rsync -a /source/directory/ /destination/directory/
これにより、ファイルコピープロセスがシステムの他の処理に影響を与えにくくなります。
バックグラウンドでの実行方法
さらに、niceコマンドと組み合わせてCPU優先度も調整することで、システムへの影響をさらに低減できます。
Bashionice -c 3 nice -n 19 rsync -a /source/directory/ /destination/directory/
nice -n 19: CPU優先度を最低に設定
このようにすることで、ファイルコピープロセスはシステムのリソースが余剰な場合にのみ実行されるようになり、通常のシステム操作への影響を最小限に抑えられます。
ステップ4:パフォーマンスモニタリング
ファイルコピーのパフォーマンスとシステムへの影響を把握するために、適切なモニタリングツールを使用することが重要です。
iostatコマンドによるI/O負荷の監視
iostatは、システムのI/O統計情報を表示するコマンドです。ファイルコピーの前後で比較することで、I/O負荷の変化を確認できます。
Bashiostat -xz 1
主な表示項目:
- %util: デバイスのI/O帯域使用率(100%に近いとボトルネックになる可能性あり)
- await: I/Oリクエストの平均応答時間
- r_await/w_await: 読み取り/書き込みの平均応答時間
ファイルコピー中に%utilが100%に近づく場合は、I/Oがボトルネックになっている可能性があります。この場合は、帯域制限やI/O優先度の調整を検討してください。
vmstatコマンドによるシステムリソースの監視
vmstatは、仮想メモリの統計情報を表示するコマンドです。I/O負荷がシステム全体に与える影響を把握するのに役立ちます。
Bashvmstat 1
主な表示項目:
- bi: ブロック入力(秒あたりのブロック数)
- bo: ブロック出力(秒あたりのブロック数)
- b: 割り込みを待つプロセス数
- cs: 上下回数(コンテキストスイッチ)
これらの値が通常時と比べて著しく増加している場合、I/O負荷がシステムに影響を与えている可能性があります。
コピー前後の比較方法
ファイルコピーのパフォーマンスを正確に評価するには、以下の手順で比較測定を行うことをお勧めします。
- ファイルコピー前に基準となるパフォーマンスデータを収集
- ファイルコピーを実行
- コピー中にパフォーマンスを監視
- コピー後に再度パフォーマンスデータを収集
- データを比較して影響を評価
例えば、以下のようなスクリプトで測定できます。
Bash#!/bin/bash # コピー前の測定 echo "=== Before copy ===" iostat -xz 1 3 > /tmp/iostat_before.txt vmstat 1 3 >> /tmp/vmstat_before.txt # ファイルコピーを実行 ionice -c 3 rsync -a /source/directory/ /destination/directory/ # コピー後の測定 echo "=== After copy ===" iostat -xz 1 3 > /tmp/iostat_after.txt vmstat 1 3 >> /tmp/vmstat_after.txt # 結果比較 echo "=== Comparison ===" diff /tmp/iostat_before.txt /tmp/iostat_after.txt diff /tmp/vmstat_before.txt /tmp/vmstat_after.txt
ハマった点やエラー解決
スケジューラ変更後のパフォーマンス問題
問題: I/Oスケジューラを変更した後、予想以上にパフォーマンスが低下した。
解決策: これは、選択したスケジューラがシステムのワークロードに適していない可能性があります。まずは元のCFQに戻して比較してみてください。
Bashecho cfq > /sys/block/sda/queue/scheduler
また、スケジューラの変更はデバイスごとに行われるため、複数のストレージデバイスを使用している場合は、それぞれのデバイスで適切なスケジューラを選択する必要があります。
Bash# 例: sdbデバイスではnoopを使用 echo noop > /sys/block/sdb/queue/scheduler
大容量ファイルコピー時のメモリ不足問題
問題: 大容量ファイルをコピーしていると、システムのメモリが不足してしまう。
解決策: rsyncの--partialオプションを使用して、中断された転送を再開可能な状態で保持することで、メモリ使用量を抑えられます。また、--bwlimitオプションで転送速度を制限することも有効です。
Bashrsync -a --partial --bwlimit=1000 /large/file /destination/
さらに、rsyncの--buffer-sizeオプションでバッファサイズを調整することもできます。
Bashrsync -a --buffer-size=8192k --partial /large/file /destination/
ネットワーク経由でのコピー時の注意点
問題: ネットワーク経由でファイルをコピーしていると、ローカルのI/O負荷は低いが、ネットワークワークロードが高くなる。
解決策: ネットワーク経由のファイル転送では、ネットワーク帯域の制限も考慮する必要があります。rsyncの--bwlimitオプションでネットワーク帯域も制限できます。
Bashrsync -a --bwlimit=1000 --partial /source/ user@remote:/destination/
また、SSH経由でファイル転送を行う場合、SSHの圧縮設定もパフォーマンスに影響します。大容量ファイルの転送では、圧縮を無効にすることでパフォーマンスが向上することがあります。
Bashrsync -avz -e "ssh -c arcfour" /source/ user@remote:/destination/
arcfourは比較的高速な暗号化アルゴリズムですが、セキュリティは標準のものより劣るため、信頼できるネットワーク内での使用に限定してください。
まとめ
本記事では、CFQを使用せずにLinuxシステムで低負荷でファイルコピーを行う方法について解説しました。I/Oスケジューラの変更、ファイルコピーコマンドの最適化、I/O優先度の調整といった具体的なテクニックを学ぶことで、システム全体のパフォーマンスを維持しながら効率的にファイル転送を行えるようになります。
実際のシステム環境では、ワークロードやストレージの特性によって最適な設定が異なります。本記事で紹介した方法を組み合わせて、自システムに最適な設定を見つけてください。また、パフォーマンスモニタリングを継続的に行い、必要に応じて設定を調整することが重要です。
今後は、より高度なファイル転送技術や、クラウド環境でのファイル操作に関する記事も予定しています。
参考資料
- Linuxカーネルドキュメント - I/O スケジューラ
- I/O Scheduler Tuning - The Linux Kernel Archives
- rsync(1) - Linux man page
- ionice(1) - Linux man page
- Linux I/O Performance Tuning
