LIVE SIMPLY

データ活用組織のマネジメントを行いつつコーチング、本など学んだことを書くblog

「なぜこのように設計されているか?」思想を知ること (ファイルディスクリプタを題材に)

今日、ファイルディスクリプタの設定値について、
現在のシステムでいくつの値に設定しようか(5000でよいのか?10000でよいのか?その根拠は?)
と悩んでいた。

■ファイルディスクリプタとは
プログラムがアクセスするファイルや標準入出力などをOSが識別するために用いる識別子。
0から順番に整数の値が割り当てられる。
http://e-words.jp/w/E38395E382A1E382A4E383ABE38387E382A3E382B9E382AFE383AAE38397E382BF.html

※背景
・ファイルやディレクトリだけではなく、ネットワーク(socket)やパイプなど、
 入出力可能なさまざまなリソースを「ファイル」として扱う
・ファイルディスクリプタとは、これらのファイルを指す識別子様々なリソースを
 ”抽象化”してファイルとして扱う

※目的
・共通的な処理をしやすくするため。
 →read()やwrite()など
 →入出力先を簡単に切り替えたりできる
  └例えばprintf()は本来、stdout(標準出力)に指定した文字を出力するが、
   >(リダイレクト)することで、この出力先を通常のファイルなどに変更可能。
   これは抽象化によって実現できていること。



参考:http://q.hatena.ne.jp/1234186442



値をいくつにすべきか?を考える前に、まず、そもそも以下の質問に答えられるか?を考えた

■ファイルディスクリプタの制限はなぜ設定されているのか?
→もし制限なければメモリが枯渇してしまうから、未然に防ぐため

■現行の上限値の設定はどうなっているか?なぜその値になっているのか?
・物理メモリ:16GB
 MemTotal: 16410952 kB
・ファイルディスクリプタ上限(システム):
 $ more /proc/sys/fs/file-max
 1517379
では、なぜこの値になっているか??

調べた結果、下記のような記述があった。

487 void __init files_init(unsigned long mempages)
488 {
489 unsigned long n;
490
491 filp_cachep = kmem_cache_create("filp", sizeof(struct file), 0,
492 SLAB_HWCACHE_ALIGN | SLAB_PANIC, NULL);
493
494 /*
495 * One file with associated inode and dcache is very roughly 1K.
496 * Per default don't use more than 10% of our memory for files.
497 */
498
499 n = (mempages * (PAGE_SIZE / 1024)) / 10;
500 files_stat.max_files = max_t(unsigned long, n, NR_FILE);
501 files_defer_init();
502 lg_lock_init(files_lglock);
503 percpu_counter_init(&nr_files, 0);
504 }


-----------------------------------------------------------------------
コメント部分の内容:
・1ファイルを開くのに、メモリはおおよそ1K割り当てられる
・ファイル関連に使用するメモリは、全体の物理メモリの10%未満にする
-----------------------------------------------------------------------

現状のシステムの設定値(プロセスごと)はこうなっている
1024

上記の調査ことからわかったことは、
(ざっくり見積もりではあるが)設定値を5000にしようが、10000にしようが、
メモリに与える影響は少ない
(5000*1K=5MB)たかだか5MBということになる
つまり、10000だから大きすぎることはないことがわかる。

以上より、今回のケースにおいては以下を考慮し、あとは決めで上限値を設定すればよいのかな・・と思う
・システムとして、間違いなく不足しないであろう値
(例えばapacheのMaxClientsの値5120+αで10000は超えないであろう・・とか)
・1000では小さい、100万では大きすぎる
・5000でも10000でもメモリに与える影響は小さいので
 メモリ影響は気にしなくてよい


2011/12/3 追記
■ファイルディスクリプタの設定値を確認する方法
▼システム全体の値を確認する
?/proc/sys/fs/配下の値を確認する
/proc/sys/fs/file-max
/proc/sys/fs/file-nr
を見る。

/proc/sys/fs/file-max
24766
→システム中のオープンファイル管理データの最大数

/proc/sys/fs/file-nr
1344 0 24766
→それぞれ、
 OS起動後これまでの最大数
 空きファイル管理データの数
 システム中のオープンファイル管理データの最大数(file-maxと同じ)
 を表す。

※注意
/proc/sys/fs/file-nrはシステム全体の値なので、ユーザごとに実行しても変わらないので注意。

?/etc/security/limits.confを確認する
→ユーザごとに設定できる!

$ more /etc/security/limits.conf | grep file
# - core - limits the core file size (KB)
# - fsize - maximum filesize (KB)
# - nofile - max number of open files
# - locks - max number of file locks the user can hold
aaa soft nofile 65536
bbb hard nofile 65536
# End of file


?sysctl コマンドで確認
# sysctl -a | grep file
fs.file-max = 24766
fs.file-nr = 1344 0 24766


▼ユーザごとの設定値を確認する
ユーザによって設定できる。 


?/etc/security/limits.confを確認する
→ユーザごとの設定値を確認。

$ more /etc/security/limits.conf | grep file
# - core - limits the core file size (KB)
# - fsize - maximum filesize (KB)
# - nofile - max number of open files
# - locks - max number of file locks the user can hold
aaa soft nofile 65536
bbb hard nofile 65536
# End of file


?ulimit -nの結果を確認する
[test01@tstweb01 ~]$ ulimit -n
1024

[test02@tstweb01 ~]$ ulimit -n
65536

[root@tstweb01 ~]# ulimit -n
1024


■設定方法
?sysctl -wで行う。
# sysctl -w fs.file-max=24765
fs.file-max = 24765

?「echo 32768 > /proc/sys/fs/file-max」で動的に変更可能

?/etc/sysctl.confに「fs.file-max=32768」を記述する


参考:
http://d.hatena.ne.jp/stealthinu/20100826/p2
http://www.atmarkit.co.jp/flinux/special/proctune/proctune01a.html