TUNING(7)

名称
tuning - FreeBSD における性能チューニング

システム設定 - disklabel, newfs, tunefs, スワップ
disklabel(8) または sysinstall(8) を使ってハードディスク上にファイルシステムをレイアウトする場合、 ディスクの内周トラックよりも外周トラックのほうがずっと速くデータを 転送できることを意識することが重要です。 この利点を生かすには、 小さいファイルシステムやスワップを外周トラックに近いほうから 詰めていくべきです。 より大きいファイルシステムは内周へ近いほうへ詰めていき、 最も大きいファイルシステムを最後にします。 後でマシンを増強した時にシステム標準のファイルシステムの大きさを 変更しなくて済むような大きさに決めることが重要です。 私は大抵、順番にルートパーティションに 128M、スワップに 1G、 /var に 128M、 /var/tmp に 128M、 /usr に 3G、 そして残りを /home に割り当てます。

典型的にはメインメモリの約 2 倍のスワップスペースを用意すべきです。 RAM がそれほど多くない場合は、一般にもっとスワップが必要でしょう。 256M より小さいスワップを設定するのは奨められません。 スワップ パーティションの大きさを決めるときは将来のメモリ増設のことを 考えておくべきです。 カーネルの VM ページングアルゴリズムは、スワップの大きさが メインメモリの少なくとも 2 倍ある場合に最高の 性能が出るようにチューンされています。 スワップを小さくしすぎると、 VM ページ走査コードが効率的に動かなくなります。 メモリをさらに追加した時も同様です。 最後に、複数の SCSI ディスク (あるいは異なるコントローラ上にある 複数の IDE ディスク) を備えた大規模なシステムにおいては、 それぞれのドライブ (最大 4 ドライブ) にスワップを置くことを強く推奨します。 各ドライブ上のスワップパーティションがほぼ同じ大きさになる ようにしてください。 カーネルは任意の大きさを扱うことができますが、内部のデータ構造は 最大のスワップパーティションのものの 4 倍の大きさになってしまいます。 スワップパーティションをだいたい同じ大きさにすることで、 カーネルは最適な方法でスワップ空間を N 台のディスクに対し ストライピングします。 少々のやりすぎを気にする必要はありません。 スワップ空間は UNIX が優雅に動作するためのものです。 普段それほどスワップを使っていなくても、 プログラムの暴走で強制的にリブートしてしまう前に、 回復作業をするための時間稼ぎになります。

/var パーティションをどれだけの大きさにするかは、そのマシンを 何に使うかということに大きく依存します。 このパーティションは主にメールボックスやプリントスプール、 ログファイルの保存場所に使われます。 /var/log を別のパーティションにする人もいます (しかし、パーティション ID を 消費しないほうが良い極端な場合は例外です)。 メールサーバやプリントサーバ、あるいは 訪問数が非常に多い Web サーバとしてマシンが動作するなら、 極めて大きいパーティション – おそらく 1 ギガバイト以上 – を 作成することを考えるべきでしょう。 ログファイルの保存に必要な大きさは、小さく見積もられがちです。

/var/tmp の大きさは、テンポラリファイルの類が どれだけ使われる必要があるかで決まります。 最低でも 128M にすることを推奨します。 また sysinstall は /tmp ディレクトリも作成します。 テンポラリファイル領域専用に 1 つのパーティションを 割り当てることは重要で、2 つの理由があります: クラッシュ時のファイルシステムの破壊の可能性を 減らすのと、 [/var]/tmp を一杯にしてしまう ような暴走プロセスが、さらに重要なサブシステム (メールやログ等) に影響を与える可能性を減らすためです。 [/var]/tmp が一杯になってしまうのはよくある問題です。

かつては /tmp と /var/tmp の間には違いがありましたが、 /var (と /var/tmp) の導入によってプログラマは大変混乱し、 今日では両方がでたらめに使われています。 つまりこの 2 つは実際には区別することができません。 したがって、1 つのテンポラリディレクトリだけにしてして、 他の tmp ディレクトリからここへソフトリンクを張ることは意味があります。 どのように /tmp を扱ったとしても、 それがルートパーティションにあるのは好ましくないでしょう。 一杯になったり、クラッシュやリブートにより破壊される 可能性があるからです。

/usr パーティションはシステムをサポートするために 必要なファイルの大部分を持っており、そのサブディレクトリ /usr/local は ports(7) 階層からインストールされるファイルの大部分が置かれます。 ports をあまり使わず、システムのソース (/usr/src) を保持するつもりがなければ /usr は 1 ギガバイトで十分でしょう。 しかし、大量の ports (特にウィンドウマネージャや Linux エミュレーションされるバイナリ) をインストールする場合は、 少なくとも 2 ギガバイトの /usr を推奨します。 さらに、システムのソースを保持するつもりであれば、3 ギガバイトの /usr を推奨します。 このパーティションに対して必要な領域の大きさを過小評価 しないでください。 これは緩やかに成長し、驚かされることになります !

/home パーティションはユーザ固有のデータを保持するのに使われます。 私は大抵ディスクの残りを使います。

何故 パーティションを切るのでしょう ? 1 つの大きな / パーティションを作るだけで良いのではないでしょうか ? そうすれば小さすぎないかどうか気にする必要はないのに ! はい、その考えが良くないのは、いくつか理由があります。 1 つめは、それぞれのパーティションは運用上の性格が 異なるのですが、それらを分離することでファイルシステムに対し その性格に適したチューンをすることが可能になるからです。 例えばルートパーティションや /usr パーティションはほとんど読み込みであり、ほとんど書き込みがありません。 一方で /var や /var/tmp に対しては大量の読み込みや書き込みがあるでしょう。 システムをうまく分割することで、書き込みが多いパーティションの破壊に よる被害が、ほとんど読み込みのみのパーティションに及ばないようします。 加えて、書き込みが多いパーティションをディスクの端 (すなわちパーティションテーブルにおいて、 本当に大きなパーティションの後ろではなく、前の方) の方に置くことで、そのパーティションについて性能が向上します。 より大きなパーティションについても入出力性能が必要なのも確かですが、 /var をディスクの端に置くと大きな改善が可能であるのに対し、 巨大なパーティションをディスクの端に置いてもそれほど性能の 改善にはつながりません。 最後は安全性に関わることです。 小さく、簡潔な、本質的に読み込みのみの ルートパーティションとすることで、クラッシュを生き延びるチャンスを 大きくすることができます。

システムを正しく分割することで、 newfs(8) や tunefs(8) に与えるパラメータをチューンすることも可能になります。 newfs() のチューニングにはさらに経験が必要ですが、かなりの性能改善につながります。 比較的安全にチューンできる 3 つのパラメータがあります: blocksize, bytes/inode, cylinders/group です。

FreeBSD は 8K または 16K のファイルシステムブロックサイズを使用した時に 最高の性能が得られます。 デフォルトは 16K であり、 ほとんどのアプリケーションで良い結果となりますが、 大きなファイルにランダムアクセスするアプリケーション (データベースサーバソフトウェア等) は例外です。 このようなアプリケーションでは、 小さなブロックサイズで良い結果となる傾向がありますが、 最近のディスクの特性においては、 小さなブロックサイズの使用は考慮に値しないでしょう。 16K より大きなブロックサイズを使用すると バッファキャッシュの断片化を招き、性能が低下します。

デフォルトは、 多大な inode を必要とするファイルシステムや、 多大な小ファイルを保持することを意図したファイルシステムには 向かないかもしれません。 このようなファイルシステムは、 8K または 4K のブロックサイズで作成されるべきです。 これはまた、小さなフラグメントサイズを指定する必要があります。 常にブロックサイズの 1/8 のフラグメントサイズにすることを推奨します (他のフラグメントサイズの割合ではあまりテストされていません)。 この場合の newfs(8) オプションは “newfs -f 1024 -b 8192 ...” となるでしょう。

大きなパーティションに、データベースファイルのような 少数の大きなファイルを置くのであれば、 bytes/inode の比率を増やすことができます。 これは、そのパーティションの inode の数 (ファイルやディレクトリの最大の数) を減らします。 inode の数を減らすことで、クラッシュ後の fsck(8) による修復時間を大幅に減らすことができます。 本当にこのパーティションに大きなファイルを置くのでない限り、 このオプションを使わないでください。 空き領域が大量にあるのにファイルを収容できなくなるかもしれません。 bytes/inode は、32768 か 65536 か 262144 とすることが推奨されます。 もっと大きな値にすることができますが、 fsck(8) による修復時間を増やすだけでしょう。 例えば、 “newfs -i 32768 ...” のようにして値を与えます。

tunefs(8) はファイルシステムをさらにチューンするのに使えます。 このコマンドは、シングルユーザモードで実行することができ、 ファイルシステムの再フォーマットは不要です。 しかし、おそらく最も誤って使用されているプログラムでしょう。 多くの人はファイルシステムの利用可能な空き領域を増やそうとして、 min-free 比率を 0 に設定します。 これはファイルシステムの猛烈な断片化につながるので、推奨されません。 ここで、唯一本当に価値がある tunefs(8) のオプションは、 “tunefs -n enable /filesystem” として softupdates を有効にすることです (注意: FreeBSD 4.5 以降では newfs(8) に -U オプションを与えることで softupdates を有効に することができます。 そして sysinstall(8) は、ルート以外のファイルシステムの softupdates を標準で 自動的に有効にします)。 softupdates はメタデータの性能、 主にファイルの作成と削除の性能を劇的に改善します。 大部分のファイルシステムで softupdates を有効にすることを推奨します。 しかしながら、ファイルシステムで softupdates を使うかどうか判断する際に 気をつけるべき 2 つの制限があります。 1 つめは、softupdates はクラッシュ時における ファイルシステムの一貫性は保証しますが、 未反映の物理ディスク書き込みより何秒か (1 分になることもあります!) おそらく遅れていることです。 クラッシュした場合、より多くの成果が消えてしまうかもしれません。 2 つめは、softupdates はファイルシステムブロックを解放するのを遅らせる ということです。 あるファイルシステム (例えばルートファイルシステム) が満杯近くの時に それに対する大規模な更新、たとえば “make installworld” をすると、空き領域を使い果たして更新が失敗してしまうことがあります。 そのため標準的なインストールではルートファイルシステムの softupdates を 有効にしません。 ルートファイルシステムは滅多に書き込まれませんので、性能上の損失はありません。

mount(8) 実行時のいくつかのオプションはファイルシステムをチューンするのに役立ちます。 最も明らかで、しかも最も危険なのは async です。 これは決して使わないでください。 大変危険です。 比較的危険度が低く、より役に立つ mount(8) のオプションは noatime です。 通常 UNIX ファイルシステムは、ファイルやディレクトリにアクセスが あった場合は常に、その最終アクセス時刻を更新します。 FreeBSD では、この動作は遅延書き込みで行なわれ、 通常は大した負荷にはなりません。 しかし、大量のファイルが連続してアクセスされた場合、 バッファキャッシュがアクセス時刻の更新で汚染され 大きな負荷となります。 例えば、高負荷の web サイトや大量の読者を抱えるニューズサーバ では、この mount(8) のオプションで大きなパーティションにおける アクセス時刻の更新を停止することが考えられます。 根拠もなく、すべての場所でアクセス時刻の更新を停止しないでください。 例えば、 /var ファイルシステムは、慣習的にメールボックスを保持し、 新規メールのメールボックス中の有無判定に atime (および mtime) が使用されます。 読み込み専用パーティション、 / や /usr では、atime をオンにしておいた方が良いでしょう。 システムユーティリティには、atime フィールドを使用するものがあるので、 / では特に有用です。

ディスクのストライピング
大きなシステムでは、いくつかのドライブのパーティションを互いに ストライピングして、全体として巨大なパーティションを作ることもあります。 ストライピングは、入出力操作を複数のディスクに振り分けることで ファイルシステムの性能を向上させることができます。 vinum(8) および ccdconfig(8) ユーティリティは、シンプルなストライピングされたファイルシステムを 作るのに使われます。 一般に、ルートや /var/tmp のような小さなパーティション、 あるいは /usr のような本質的に読み込みのみのパーティションを ストライピングしても時間の無駄にしかなりません。 本当に入出力性能を必要とするパーティションのみをストライピングするべきです。 典型的には /var や /home あるいはデータベースや Web ページを 保持するカスタムパーティションです。 適切なストライプサイズを選ぶことも重要です。 ファイルシステムはメタデータを 2 の累乗の境界で格納する傾向にあり、 大抵はシークを増やすのではなく減らしたいでしょう。 これは、1152 セクタといったような、 シーケンシャルな I/O が両方のディスクをシークしないように、 かつメタデータが単一のディスクに集中するのではなく両方に分散するような、 中心を外れた (off-centered) 大きな ストライプサイズにしたい、ということを意味します。 本当に性能が必要なら、 FreeBSD がサポートする本物のハードウェア RAID コントローラを 使うことを勧めます。

sysctl によるチューニング
sysctl(8) 変数は、実行時に、システムの動作のモニタおよび制御を可能とします。 sysctl には、単にシステムの動作を報告するものもありますが、 システムの動作を変更するものもあります。 ブート時に rc.conf(5) を使用して設定可能なものもありますが、大部分は sysctl.conf(5) で設定可能です。 システムには数百の sysctl(8) 変数が存在します。 そのなかには、チューニングの候補のように見えますが本当は そうでないものも多く含まれます。 この文書では システムに最も大きな影響を与えるものだけを扱います。

kern.ipc.shm_use_phys sysctl は、デフォルトが 0 (オフ) であり、 0 (オフ) または 1 (オン) にセットすることができます。 このパラメータを 1 にセットすると、全ての System V 共有メモリセグメントが ページング不可の物理メモリにマップされます。 これは、(A) 大量 (数百) のプロセス間で少量の共有メモリを マッピングしているか、(B) 任意個のプロセス間で大量の共有メモリを マッピングしている、のいずれかの場合に効果があります。 この機能は、共有メモリをスワップ不可にすることで、 共有メモリをコアに結び付ける時に生じる、 カーネルにおける内部のメモリ管理によるページ追跡 オーバヘッドをかなり減らします。

vfs.vmiodirenable sysctl は、デフォルトは 0 (オフ) であり (しかし近いうちにデフォルトが 1 に なるでしょう)、0 (オフ) または 1 (オン) にセットすることができます。 このパラメータは、ディレクトリがシステムによってどのように キャッシュされるかを制御します。 ほとんどのディレクトリは小さく、 ファイルシステムにおいては単一フラグメント (典型的には 1K) であり、バッファキャッシュではさらに小さくなっています (典型的には 512 バイト)。 しかし、デフォルトモードで動作している時は、 大量のメモリを搭載していても バッファキャッシュは固定数のディレクトリしかキャッシュしません。 この sysctl をオンにすると、バッファキャッシュが VM ページキャッシュを、ディレクトリをキャッシュするために使うことを可能に します。 これによる利点は、全てのメモリがディレクトリを キャッシュするのに使えるようになるということです。 欠点は、キャッシュに使われる最小のメモリの大きさが 512 バイトではなく 物理ページサイズ (大抵は 4K) になることです。 メモリに制約があるシステムでは、 このオプションをオフにすることを推奨します。 一方、オンにすると、多数のファイルを操作するサービスの性能が向上します。 そのようなサービスには、web キャッシュや、大規模なメールシステム、 ニューズシステムなどが含まれます。 このオプションは一般に メモリを消費しますが、性能を削減することはありません。 ただし実験して調べてみるべきでしょう。

vfs.write_behind sysctl は、デフォルトで 1 (オン) です。 これによって、 ファイルシステムからメディアへの書き込みが、クラスタ分が集まった時に 発行されるようになります。 そのような状況は、典型的には、大きな シーケンシャルファイルへ書き込んでいる時に起こります。 これは、I/O パフォーマンスに寄与しないであろう場合に、 ダーティなバッファでバッファキャッシュが飽和するのを避けるという アイデアです。 しかしながら、これによってプロセスが止まるかも しれないので、状況によっては この機能を切りたいと望むかもしれません。

vfs.hirunningspace sysctl は、任意の時点においてシステム全体で、 ディスクコントローラのキューに入れて未完了状態にして良い、 書き込み I/O の量を決定します。 通常、デフォルト値で十分ですが、 ディスクをたくさん持つマシンでは 4、5メガバイトに増やしたくなるかもしれません。 値を大きくしすぎる (バッファキャッシュの 書き込みの閾値を超えて) と、クラスタリングの効果が極端に悪くなる 可能性があるので注意してください。 この値を思いつきで大きくしては いけません! また書き込みのキュー値を大きくすると、同時に発生した 読みだしが待たされるかもしれません。

他にもバッファキャッシュと VM ページキャッシュに関連した、様々な sysctl が 存在します。 これらを変更することは推奨されません。 FreeBSD 4.3 について言えば、VM システムは自分自身のチューニングに関して大変良い 仕事をしています。

net.inet.tcp.sendspace sysctl と net.inet.tcp.recvspace sysctl は、ネットワークに関連するアプリケーションを 稼動している場合は特に重要です。 これは、TCP コネクションの 送信および受信バッファ領域の大きさを調節します。 デフォルトでは、送信バッファは 32K で、受信バッファは 64K です。 このデフォルトを増やすことで 各コネクションについてカーネルメモリがさらに消費されますが、 帯域幅の利用率が改善することがあります。 同時に数百とか数千のコネクションを扱っている場合、 このデフォルトを増やすことは推奨されません。 失速してしまったコネクションが蓄積することで、 システムがメモリをすぐに使い果たしてしまうからです。 しかし、少ない数のコネクションについて広い帯域幅が必要ならば、 特にギガビットイーサネットの場合、このデフォルトを大幅に増やす ことができます。 入力データと出力データのバッファを個別に調整することができます。 たとえば、主に web サービスをしているマシンならば recvspace を 減らすことで、それほど大量にカーネルメモリを消費せずに sendspace を増やすことができます。 経路表 ( route(8) を参照 ) に対しては、経路に特化した送受信バッファを導入することが できるということに注意してください。

付加的な管理ツールとして、ファイアウォールルールにおいて パイプ (pipe) を使うことで ( ipfw(8) を参照)、特定の IP ブロックやポートへ行く、あるいはそこから 来る帯域幅を制限することができます。 例えば T1 回線を持っている場合、 web トラフィックは回線の 70% に制限し、残りをメールと インタラクティブな用途に使いたいと思うでしょう。 通常高い負荷の web サーバは、ネットワーク回線が 使い切られていても、他のサービスに大きな遅延を与えることは ありませんが、制限をかけることは物事を円滑にし長期的な安定につながります。 また、多くの人が、帯域超過による課金をされないように 意図的な帯域制限をかけています。

net.inet.tcp.rfc1323 sysctl で制御可能な TCP プロトコルのウィンドウスケーリング拡張を 両方のホストがサポートしない限り、 TCP の送信あるいは受信バッファサイズを 65535 を超えて指定しても ほとんど性能の改善はありません。 ある種のネットワークリンクから良い性能を引き出すために、 これらの拡張を有効にし、 TCP バッファサイズを 65536 より大きく設定すべきです。 特に、ギガビット WAN リンクや、高レイテンシの衛星リンクが対象となります。 RFC1323 サポートは、デフォルトでオンになっています。

net.inet.tcp.always_keepalive sysctl は、TCP 実装が、コネクション上に断続的に “keepalives” を配送することで死んでしまった TCP コネクションの検出を試みるか どうかを決定します。 デフォルトで、これはすべてのアプリケーションについて許可されています。 この sysctl を 0 に設定すると、特に keepalives を要求した アプリケーションだけが検出機能を利用できます。 大抵の環境において、死んでしまった TCP コネクションを失効にすることで、 TCP keepalives はシステム状態の管理を改善します。 特にダイヤルアップのユーザにサービスを提供しているシステムでは 効果があります。 なぜならユーザがネットワークとのコネクションを切る前に いつも個々の TCP コネクションを終了するとは限らないからです。 しかしながら、ある種の環境では、一時的なネットワークの停止が 誤ってセッションの死と判断されるかもしれません。 結果として 予期しない TCP コネクションの終了となります。 その様な環境では、sysctl を 0 に設定することで、 TCP のセッション切断の発生を減らせるかもしれません。

net.inet.tcp.delayed_ack TCP 機能は大きく誤解されています。 歴史的には、この機能は、転送されたデータに対する確認応答を、 応答と共に返せるようにするためにデザインされました。 例えば、リモートシェル上でキー入力しているとき、 あなたが送信した文字への確認応答は、文字のエコーを表すデータと共に返されます。 遅延確認応答をオフにすると、 リモートサービスが丁度受け取ったデータをエコーする機会を得る前に、 確認応答がそれだけを含むパケットで送られてしまうかもしれません。 この同じ考え方がすべての対話的プロトコル (例 SMTP, WWW, POP3) にあてはまり、 ネットワークの片一方を流れている小パケットを減らせるのです。 FreeBSD の遅延確認応答の実装も、TCP プロトコルの規則に従っています。 すなわち、標準の 100ms のタイムアウトが経過しなくても、 2 パケットに 1 回は確認応答を行います。 通常、遅延確認応答が行う最悪のことは、コネクションの破壊を少々遅らせること、 スロースタート TCP コネクションの立ち上がりを少々遅らせることです。 確かなことは分かりませんが、 SAMBA や SQUID といった package に関連する FAQ が 遅延確認応答をオフにするように勧めているのは、 スロースタートの問題に言及しているのでしょう。 FreeBSD では、スロースタートフライトサイズを net.inet.tcp.slowstart_flightsize sysctl で増やすことの方が、遅延確認応答をオフにするより、利益があるでしょう。

net.inet.tcp.inflight_enable sysctl は、すべての TCP コネクションに対し、 バンド幅と遅延の積による制限を適用します。 システムは、各コネクションに対してバンド幅と遅延の積を計算し、 ネットワークにキューされるデータ量を、 最適なスループットを確保するのに必要な量に限定しようとします。 この機能が有用なのは、モデムやギガビットイーサや高速 WAN リンク (といったバンド幅と遅延の積が大きなネットワーク) 経由でデータを 提供している場合であり、 特に有用なのは、ウィンドウスケーリングを併用している場合や 大きな送信ウィンドウを設定した場合です。 本オプションを有効にする場合、 net.inet.tcp.inflight_debug を 0 (デバッグ無効) に設定することを忘れずに。 実運用では、 net.inet.tcp.inflight_min を少なくとも 6144 に設定すると有用でしょう。 しかしながら、最低値を大きく設定すると、 リンクによってはバンド幅制限を無効にする結果となり得ることに注意してください。 本限定機能は、 中間ルータやスイッチのパケットキューに蓄積されるデータ量を減らし、 ローカルホストのインタフェースキューに蓄積されるデータ量をも減らします。 キューされるパケット数が少ないと、対話的コネクション、 特に低速モデム経由のものは、短い往復時間での動作が可能になります。 しかしながら、この機能はデータ送信 (アップロード / サービス側) にのみ影響することに注意してください。 データ受信 (ダウンロード) には影響しません。

net.inet.tcp.inflight_stab の調整はお勧めしません。 このパラメータのデフォルトは 20 であり、 バンド幅と遅延の積のウィンドウ計算に対して 2 個の極大パケットが追加されることを示します。 アルゴリズムの安定化のために、追加のウィンドウが必要となり、 状態の変化に対する応答性を高めます。 しかしながら、遅いリンク越しでは、ping の遅延を大きくしてしまいます (それでも、inflight アルゴリスム無しと比べれば、低いものです)。 このような場合、このパラメータを 15, 10, 5 に減らし、 net.inet.tcp.inflight_min も (例えば 3500 へ) 減らすことで、望む効果が得られるかもしれません。 これらのパラメータを減らすのは、最終手段としてください。

net.inet.ip.portrange.* sysctls は、 自動的に TCP や UDP ソケットに結合されるポート番号の範囲を制御します。 3 種類の範囲があります。 すなわち、下位の範囲、デフォルトの範囲、高位の範囲であり、 IP_PORTRANGE setsockopt(2) 呼び出しで選択可能です。 ほとんどのネットワークプログラムが使用するのはデフォルトの範囲であり、 net.inet.ip.portrange.first と net.inet.ip.portrange.last で制御されます。 それぞれ 1024 と 5000 がデフォルトです。 範囲を限定されたポート範囲は外向きコネクションに使用され、 ある条件下ではシステムがポートを使い尽してしまう場合があります。 これは、高負荷のウェブプロキシを実行している場合に、よく発生します。 通常のウェブサーバ等の主に内向きコネクションを扱うサーバや、 メールリレー等の外向きコネクションが限られているサーバを実行している場合、 これは問題とはなりません。 ポートを使い果たしてしまう場合、適度に net.inet.ip.portrange.last を増やしてみてください。 10000, 20000, 30000 といった値は大丈夫でしょう。 ポートの範囲を変えるときには、ファイアウォールの影響も考慮に入れるべきです。 ファイアウォールによっては、広い範囲のポート (通常は下位のポート) を遮蔽し、システムが高位のポートを外向きコネクションに 使用することを期待します。 このため、 net.inet.ip.portrange.first を低下させることはお勧めできません。

kern.ipc.somaxconn sysctl は、新しい TCP コネクションを受け付けるための listen キューの サイズを制限します。 高負荷の web サーバ環境では、 デフォルト値の 128 は新しいコネクションを余裕をもって扱うには低すぎます。 そのような環境では、この値を 1024 以上に増やすことが推奨されます。 サービスデーモン (例えば sendmail(8) や apache) は自分自身の listen キューのサイズを制限しているかもしれませんが、設定ファイルで キューのサイズを増やすディレクティブを持つようになるでしょう。 listen キューを大きくすることは、サービス拒否攻撃を防ぐのにも役立ちます。

kern.maxfiles sysctl は、システムがどれだけの数のファイルをオープンできるかを 決めます。 デフォルトは典型的には数千ですが、データベースや記述子を 大量に使うデーモンを稼働している場合は 10000 や 20000 に引き上げる必要 があるかもしれません。 読み込み専用の kern.openfiles sysctl を検査することで、システム上で開かれているファイル数を判定可能です。

vm.swap_idle_enabled sysctl は、多数のユーザがシステムに出入りして大量のアイドルプロセスが ある大きなマルチユーザシステムで便利です。 そのようなシステムでは、フリーメモリの予約に対し、 継続して重大な負担をかける傾向にあります。 これをオンにして vm.swap_idle_threshold1 sysctl と vm.swap_idle_threshold2 sysctl でスワップアウトヒステリシス (アイドルの秒数) を調整することで アイドルプロセスに与えられているページの優先度を通常のページアウト アルゴリズムよりも速やかに下げることができます。 これはページアウトデーモンを手助けします。 必要がないかぎり、 このオプションはオンにしないでください。 これによって起こるトレードオフは、本質的に、 スワップとディスク帯域幅をより多く消費してメモリのプリページングを より早いうちに行うことだからです。 小さなシステムではこのオプションは有害となるでしょうが、 すでにある程度ページングが発生している大きなシステムでは、 このオプションによって、全体のプロセスがより容易にメモリへ入ったり 出たりするようにできるでしょう。

ローダのチューナブル
システムの動作の一部は、 そのためのメモリ割り当てをブート処理の初期に行う必要があるために、 実行時には調整不可能です。 ローダのチューナブルを変更するには、これらの値を loader.conf(5) に設定し、システムをリブートする必要があります。

kern.maxusers は、静的なシステムテーブルの大きさを制御します。 これには、 オープンファイルの最大数、ネットワークメモリ資源の大きさ等が含まれます。 FreeBSD 4.5 の時点では、 kern.maxusers は、ブート時に、システムで利用可能なメモリ量に応じて、 大きさが自動的に決定されます。 また、実行時に、読み取り専用の kern.maxusers sysctl 値を見て決定することも可能です。 サイトによっては、 kern.maxusers を大きくしたり小さくしたりする必要があり、 これはローダチューナブルで設定可能です。 64, 128, 256 は、変な値ではありません。 膨大なファイル記述子が必要なのでない限り、 256 より大きくすることは勧められません。 kern.maxusers によってデフォルト値が決定される多くのチューナブル値は、 本文書の別の場所に記述した方法で、 個々にブート時または実行時に上書き可能です。 FreeBSD 4.4 より古いシステムでは、 カーネルの config(8) オプションの maxusers を設定する必要があります。

kern.ipc.nmbclusters を調整することで、システムが割り当てようとしている ネットワーク mbuf の数を増やすことができます。 それぞれのクラスタは約 2K のメモリに相当するので、 1024 は 2M のカーネルメモリをネットワークバッファに 予約することを示します。 簡単な計算でどれだけ必要なのかがわかります。 web サーバが同時に最大 1000 本のコネクションを扱い、 各コネクションが 16K の受信バッファと 16K の送信バッファを消費する場合、 約 32MB に相当するネットワークバッファを扱う必要があります。 経験から得た方法によると、2 倍すると良いとされています。 つまり 32MBx2 = 64MB/2K = 32768 です。 したがって、この場合は kern.ipc.nmbclusters を 32768 に設定します。 中くらいの量のメモリが搭載されたマシンでは 1024 から 4096、 さらに大量のメモリが搭載されているなら 4096 から 32768 の値を 推奨します。 決して大きい値を指定すべきではありません。 ブート時にクラッシュを引き起こす可能性があります。 netstat(1) に -m オプションを与えることで、ネットワーククラスタの使用状況が分かります。 古い FreeBSD ではこのチューナブルを持ちませんので、 代りにカーネルの config(8) オプションの NMBCLUSTERS を設定する必要があります。

ますます多くのプログラムが sendfile(2) システムコールを使ってネットワークを通じてファイルを 転送しています。 kern.ipc.nsfbufs sysctl は sendfile(2) の実行時にファイルシステムバッファをどれだけの数だけ 使えるかを制御します。 通常このパラメータは kern.maxusers に比例しているので、極端な場合を除いては このパラメータに手を出す必要はありません。 詳細は、 sendfile(2) マニュアルページの チューニング 節を参照してください。

カーネル構成におけるチューニング
大規模なシステムでは、いくつかのカーネルオプションを操作しなければ ならないかもしれません。 これらのオプションを変更する場合、あなたは ソースから新しいカーネルをコンパイルできなければなりません。 config(8) マニュアルページやハンドブックが良い入門となるでしょう。 あなただけのカスタムカーネルを作るときに一般に最初にすることは、 使用しないドライバやサービスをすべて削ることです。 INET6 や使わないドライバを削除することで、カーネルのサイズを時に 1 メガバイト以上減らすことができ、アプリケーションにさらに メモリを与えることができます。

SCSI_DELAY と IDE_DELAY は、システムの起動時間を減らすために使うことができます。 このデフォルト値はかなり大きく、ブート処理の中で 15 秒以上を占めるでしょう。 SCSI_DELAY を 5 秒に減らしても大抵はうまく動きます (特に最近のドライブでは)。 IDE_DELAY を減らしてもうまくいきますが、少々慎重になる必要があります。

*_CPU オプションの多くはコメントアウトできます。 そのカーネルを Pentium クラスの CPU だけで動かすなら、 I386_CPU と I486_CPU は削除することができます。 ただし、 I586_CPU は、CPU が Pentium II 以上として認識されることを確認してから 削除してください。 Pentium や 486 としてさえ認識されるクローンが存在し、 その場合はこれらのオプションがないと起動することができません。 もし動いたらすごいことです ! オペレーティングシステムは、MMU や タスク切り替え、タイムベース、デバイス操作に至る、より高度な機能を より利用することができるようになります。 加えてより高度な CPU は、カーネルがカーネル自身をメモリにマップする 4MB の MMU ページをサポートします。 これは高いシステムコール負荷の 下での効率を上げます。

IDE ライトキャッシュ
FreeBSD 4.3 では IDE のライトキャッシュがオフになりました。 これは IDE ディスクへの書き込み帯域幅を減らしてしまうことになりますが、 ハードドライブベンダに起因するデータの一貫性に関する重大な問題のために、 必要なことだと考えられました。 基本的には、書き込み完了時期について IDE ドライブが嘘をつくという問題です。 IDE ライトキャッシュがオンであると、 IDE ハードドライブはデータを順番に書きこまないばかりか、 ディスクの負荷が高い時にはいくつかのブロックの書き込みを 無期限に延期してしまいます。 クラッシュや電源故障の場合、ファイルシステムの重大な破壊を もたらします。したがって私たちはデフォルトを安全側に変更しました。 残念ながら、これは大変な性能の低下をもたらし、私たちはあきらめて このリリース後にオンに戻しました。 hw.ata.wc sysctl 変数を見て、デフォルトをチェックしてみるべきです。 もし IDE ライトキャッシュがオフになっていたら、 hw.ata.wc ローダチューナブルを 1 に設定することでオンに戻すことができます。 ATA ドライバシステムのチューニングに関する更なる情報は、 ata(4) を参照してください。

IDE ハードドライブの実験的な新機能として、 hw.ata.tags と呼ばれるものがあり (これもブートローダで設定します)、 ライトキャッシュを安全にオンにすることができます。 これは SCSI のタギング機能を IDE ドライブに持ち込んだものです。 これを書いている時点では、IBM DPLA と DTLA ドライブだけがこの機能を サポートしています。 警告! これらのドライブは品質管理に問題 があるようなので、私は現時点ではこれらの製品を買うことはおすすめしません。 性能が必要なら SCSI を使いましょう。

CPU、メモリ、ディスク、ネットワーク
負荷が上がるとシステムのどの部分がボトルネックになりはじめているかによって、 チューニングの種類が違ってきます。 CPU を使い果たしている (アイドル時間が常に 0%) ならば、CPU を アップグレードしたり SMP マザーボード (CPU を複数にする) に移行 したり、あるいは負荷の原因となっているプログラムを見直して最適化する ことを考える必要があるでしょう。 スワップに対して大量のページングがあるなら メモリをもっと増やす必要があるでしょう。 ディスク性能が飽和している場合、CPU アイドル時間は高く、全般的に ディスクが飽和状態になっています。 systat(1) でこれらをモニタすることができます。 ディスク性能の飽和を解決するにはいろいろな方法があります: キャッシュのためのメモリを増やす、ディスクをミラーリングする、 複数のマシンに操作を分散させる等です。 ディスク性能が問題で、IDE ドライブを使っている場合、 SCSI に切り替えることでずいぶんよくなります。 生のシーケンシャルな帯域幅については、最近の IDE ドライブは SCSI のものに 匹敵していますが、調べると大抵 SCSI ドライブが勝っています。

最後に、ネットワーク性能を使い果たしているかもしれません。 ネットワーク性能を改善するために最初に確認すべきことは、 ハブではなくスイッチを使っているか、ということです。 特に最近はスイッチは安くなっています。 ハブが高負荷になると、コリジョンバックオフのために深刻な問題が発生します。 また、1 台のホストに問題があると、LAN 全体の性能を大幅に低下させます。 次に、できるだけネットワーク経路を最適化することです。 例えば firewall(7) で説明した内部ホストを守るファイアウォールでは、 外部から見えるホストはファイアウォールを通さないトポロジです。 必要に応じて 10BaseT ではなく 100Base-T を、あるいは 100BaseT ではなく 1000BaseT を使いましょう。 最大のボトルネックは WAN 回線です (モデム、T1、DSL 等)。 回線を増強できないのであれば、 dummynet(4) 機能を使ってピーク削減やその他のトラフィックシェイピングを 行い過負荷のサービス (web サービス等) が他のサービス (電子メール等) に影響を与えるのを防いでください。逆もまた同様です。 これは、家庭環境において、外部に公開しているサービス (web サービスや電子メール) よりも インタラクティブなトラフィック (ブラウザや ssh(1) ログイン) を 優先するために使うことができるでしょう。

関連項目
netstat(1), systat(1), ata(4), dummynet(4), login.conf(5), rc.conf(5), sysctl.conf(5), firewall(7), hier(7), ports(7), boot(8), ccdconfig(8), config(8), disklabel(8), fsck(8), ifconfig(8), ipfw(8), loader(8), mount(8), newfs(8), route(8), sysctl(8), sysinstall(8), tunefs(8), vinum(8)

歴史
tuning マニュアルページは、もともと Matthew Dillon によって書かれました。 最初に登場したのは FreeBSD 4.3 で、2001 年 5 月のことです。