0
Pythonista も
ls を読むべきか?
藤原 克則 @flyingfoozy
自己紹介
O 藤原 克則

(FUJIWARA Katsunori)
O ホームページ
http://www.lares.dti.ne.jp/~foozy/index.ja.html

O ブログ
http://d.hatena.ne.jp/flying...
O 分散リポジトリ型履歴管理ツール

Mercurial の翻訳コミッタ/コントリビュータ
O Mercurial の hack に特化した
なんちゃって Pythonista
O Solaris 上で稼働させる

HPC 向けファイルシステムの実装などを
仕事でやっていたことも
O 「Tokyo OpenSolaris 勉強会」 で
Solarisカーネルの実装に関する勉強とか
http://www.opensola...
執筆過程で見つけた
バグの修正パッチが
ソースツリーに取り込まれた
GNU coreutils の ls は
ワシが育てた!
(約1/4900)
本日のお題は….
Pythonista も
ls を読むべきか?
Pythonista:
「os.listdir() を使うから
読まなくても良くねぇ?」
例えばこんな感じ?
import os
for e in os.listdir(path):
fullpath = os.path.join(path, e)
if os.path.isdir(fullpath):
# ディレクトリに対する処理...
そんな実装では
スケールしない!!!
システムコール
呼び出しコスト
O os.path.isdir(), os.path.isfile() ... は

判定処理毎に lstat(2) 呼び出し
O 呼び出し頻度は
「要素数 × 平均的な if 判定数」
O コンテキストスイッチ...
多少コスト意識が
ある場合は….
import os, stat
for e in os.listdir(path):
fullpath = os.path.join(path, e)
st = os.lstat(fullpath)
if st...
それでも残る
性能劣化要因
要因 (1) ~
os.lstat() 呼び出しコスト
O os.listdir() は

内部的に readdir(3) を使用
O readdir(3) が返す struct dirent は
要素種別情報 d_type を保持
O 種別情...
要因 (2) ~
ファイル名解決コスト
O OS内部でのファイル名解決

(ファイル名⇒対象の管理情報)は
パス要素毎の繰り返し処理で実現
O os.lstat() に指定されるファイル名にも
同様の解決コストが必要
“foo/bar/baz/file” に対する
OS内部でのファイル名解決例
1.
2.
3.
4.
5.

“.” への “foo” の問い合わせ
“./foo" 相当の管理情報の取得
“./foo” への “bar” の問い合わせ
“./f...
ファイル名解決における
直接的なコスト
O ディレクトリ階層の深さ

⇒ 繰り返しによるコストの高低
O 配下要素の多寡
⇒ 要素有無の確認コストの高低
O OS/ファイルシステム毎に色々な性能改善策

(名前解決キャッシュ/木構造管理/ハッシ...
ファイル名解決における
間接的なコスト
O 階層/配下要素の増加による I/O 量の増加
O メモリアクセスと比べて、

圧倒的にコストが高い
O I/O 対象の散在によるシークコストの増加
O 記録媒体が HDD であれば、

ミリ秒単位の ...
性能劣化の低減策
低減策 (1) ~
os.lstat() 呼び出しの低減
O readdir(3) が返す struct dirent には

各要素の種別情報を保持する
d_type フィールドがある
O 種別情報のみで事足りるなら
lstat(2) 呼び出...
低減策 (2) ~
ファイル名解決コストの低減
O fstatat(2) システムコールの利用
O SYNOPSYS
int fstatat(int dfd,
const char *path, struct stat *buf,
int fl...
低減策の効果計測
基本条件
O 1.8GHz 4 core Atom 環境
O I/O 要因での性能劣化を極力防止
O メモリファイルシステム上でテスト

O 常に現ディレクトリからの相対アクセス
O 必要なファイル/ディレクトリ要素のみ
lstat(2) 実行のコスト
O 実行条件
O 1000 要素を保持するディレクトリ
O 1000 要素それぞれへの lstat(2) 実施

O 計測結果
O 1000 回繰り返しで 3 ~ 4 秒の違い
O lstat(2) 実行コストは...
ファイル名解決のコスト
O 実行条件
O 現ディレクトリから 10 階層隔てる
O 1000 要素を保持するディレクトリ
O 1000 要素それぞれへの

lstat(2) または fstatat(2) 実施
O 計測結果
O 1000 回繰り...
性能計測の評価
O 対象10,000超で体感的な差が出る可能性
O システムコールのコスト差だけでも

対象1,000,000なら数秒オーダーの差
O 実際の環境では、性能劣化要因が増える
O ディレクトリ階層が複雑化した場合

ファイル名解決...
低減策の問題点
環境毎の仕様準拠
O dirent.d_type による種別情報の提供は

POSIX 標準ではオプション扱い
O GNU coreutils の ls でも

使用可能な環境では使用
O fstatat(2) の標準化は XPG7 (2013...
Python からの利用可能性
O Python の標準 API からは

dirent.d_type も fstatat(2) も使えない
Python から使えないなら
そんな話するな!
そんな時の為の
C ライブラリ連携!
Mercurial における
listdir() の独自実装
まーきゅりあるノ話ヲ
シタイダケデハ
ナイデスヨ?(棒)
O ディレクトリ配下要素の

情報取得を行う機能 osutil.listdir() を
MercurialではCライブラリとして独自実装
O システムコール実行コストを
環境に応じて極力低減
O DT_REG マクロ判定

(dirent.d_...
結論
ls.c は読まなくても….
O mercurial/osutil.c の listdir() 実装は

読んでおいた方が良いかもね!
O ディレクトリ要素や要素毎情報の取得で
使用している API を把握しよう
O API 使い分けによる
性...
Pythonista も….
O 「lsを読まずにプログラマを名乗るな!」を

買ってね!
O OS の内部処理とかファイルシステム周りの
話も盛り込んであるよ!
参考資料
Mercurial
O プロジェクトページ
http://mercurial.selenic.com/

O mercurial/osutil.c
http://selenic.com/repo/hg/file/stable/mercurial...
POSIX仕様
O XPG6: IEEE Std 1003.1, 2004 Edition
http://pubs.opengroup.org/onlinepubs/9699919799/

O XPG7: IEEE Std 1003.1, 2...
GNU coreutils
O プロジェクトページ
http://www.gnu.org/software/coreutils/

O src/ls.c
http://git.savannah.gnu.org/cgit/coreutils.gi...
「lsを読まずに
プログラマを名乗るな!」
O 書籍情報
http://www.shuwasystem.co.jp/products/7980html/3943.html

O サポートページ
http://www.lares.dti.ne.j...
おしまい
Pythonista も ls を読むべきか?
Pythonista も ls を読むべきか?
Upcoming SlideShare
Loading in...5
×

Pythonista も ls を読むべきか?

4,206

Published on

Python Developers Festa 2013.11 での発表資料です。
https://github.com/pyspa/pyfes/blob/develop/201311.rst
性能計測結果は Solaris 系の OpenIndiana 151a 上で実施したものですので、他の OS の場合は異なる傾向となる可能性もあります。

Published in: Technology
0 Comments
17 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
4,206
On Slideshare
0
From Embeds
0
Number of Embeds
6
Actions
Shares
0
Downloads
19
Comments
0
Likes
17
Embeds 0
No embeds

No notes for slide

Transcript of "Pythonista も ls を読むべきか?"

  1. 1. Pythonista も ls を読むべきか? 藤原 克則 @flyingfoozy
  2. 2. 自己紹介
  3. 3. O 藤原 克則 (FUJIWARA Katsunori) O ホームページ http://www.lares.dti.ne.jp/~foozy/index.ja.html O ブログ http://d.hatena.ne.jp/flying-foozy/ O Twitter @flyingfoozy
  4. 4. O 分散リポジトリ型履歴管理ツール Mercurial の翻訳コミッタ/コントリビュータ O Mercurial の hack に特化した なんちゃって Pythonista
  5. 5. O Solaris 上で稼働させる HPC 向けファイルシステムの実装などを 仕事でやっていたことも O 「Tokyo OpenSolaris 勉強会」 で Solarisカーネルの実装に関する勉強とか http://www.opensolaris.gr.jp/study.html O 下位レイヤの話も好き
  6. 6. 執筆過程で見つけた バグの修正パッチが ソースツリーに取り込まれた
  7. 7. GNU coreutils の ls は ワシが育てた! (約1/4900)
  8. 8. 本日のお題は….
  9. 9. Pythonista も ls を読むべきか?
  10. 10. Pythonista: 「os.listdir() を使うから 読まなくても良くねぇ?」
  11. 11. 例えばこんな感じ? import os for e in os.listdir(path): fullpath = os.path.join(path, e) if os.path.isdir(fullpath): # ディレクトリに対する処理 elif os.path.isfile(fullpath): # ファイルに対する処理 .....
  12. 12. そんな実装では スケールしない!!!
  13. 13. システムコール 呼び出しコスト O os.path.isdir(), os.path.isfile() ... は 判定処理毎に lstat(2) 呼び出し O 呼び出し頻度は 「要素数 × 平均的な if 判定数」 O コンテキストスイッチを生じるので 通常の関数呼び出しよりも 圧倒的にコストが高い
  14. 14. 多少コスト意識が ある場合は…. import os, stat for e in os.listdir(path): fullpath = os.path.join(path, e) st = os.lstat(fullpath) if stat.S_ISDIR(st.st_mode): # ディレクトリに対する処理 elif stat.S_ISREG(st.st_mode) # ファイルに対する処理 .....
  15. 15. それでも残る 性能劣化要因
  16. 16. 要因 (1) ~ os.lstat() 呼び出しコスト O os.listdir() は 内部的に readdir(3) を使用 O readdir(3) が返す struct dirent は 要素種別情報 d_type を保持 O 種別情報のみで事足りる場合 os.lstat() 呼び出し自体が不要な筈 (サイズや日時情報が必要ない場合等)
  17. 17. 要因 (2) ~ ファイル名解決コスト O OS内部でのファイル名解決 (ファイル名⇒対象の管理情報)は パス要素毎の繰り返し処理で実現 O os.lstat() に指定されるファイル名にも 同様の解決コストが必要
  18. 18. “foo/bar/baz/file” に対する OS内部でのファイル名解決例 1. 2. 3. 4. 5. “.” への “foo” の問い合わせ “./foo" 相当の管理情報の取得 “./foo” への “bar” の問い合わせ “./foo/bar” 相当の管理情報の取得 “./foo/bar” への .......
  19. 19. ファイル名解決における 直接的なコスト O ディレクトリ階層の深さ ⇒ 繰り返しによるコストの高低 O 配下要素の多寡 ⇒ 要素有無の確認コストの高低 O OS/ファイルシステム毎に色々な性能改善策 (名前解決キャッシュ/木構造管理/ハッシュテー ブル) O 運用回避 e.g.ディレクトリ配下の要素数に上限を設ける (proxyサーバやブラウザのキャッシュ)
  20. 20. ファイル名解決における 間接的なコスト O 階層/配下要素の増加による I/O 量の増加 O メモリアクセスと比べて、 圧倒的にコストが高い O I/O 対象の散在によるシークコストの増加 O 記録媒体が HDD であれば、 ミリ秒単位の I/O 待ち状態 O GHz クラスの CPU なら、 単純計算でも百万命令単位分の I/O 待ち
  21. 21. 性能劣化の低減策
  22. 22. 低減策 (1) ~ os.lstat() 呼び出しの低減 O readdir(3) が返す struct dirent には 各要素の種別情報を保持する d_type フィールドがある O 種別情報のみで事足りるなら lstat(2) 呼び出し自体が不要
  23. 23. 低減策 (2) ~ ファイル名解決コストの低減 O fstatat(2) システムコールの利用 O SYNOPSYS int fstatat(int dfd, const char *path, struct stat *buf, int flag); O 起点ディレクトリ(dfd)からの相対的名前解決 O 直下の要素なら問い合わせは1階層限定 O I/O対象を局所化可能
  24. 24. 低減策の効果計測
  25. 25. 基本条件 O 1.8GHz 4 core Atom 環境 O I/O 要因での性能劣化を極力防止 O メモリファイルシステム上でテスト O 常に現ディレクトリからの相対アクセス O 必要なファイル/ディレクトリ要素のみ
  26. 26. lstat(2) 実行のコスト O 実行条件 O 1000 要素を保持するディレクトリ O 1000 要素それぞれへの lstat(2) 実施 O 計測結果 O 1000 回繰り返しで 3 ~ 4 秒の違い O lstat(2) 実行コストは 1回あたり 3 usec ~ 4 usec
  27. 27. ファイル名解決のコスト O 実行条件 O 現ディレクトリから 10 階層隔てる O 1000 要素を保持するディレクトリ O 1000 要素それぞれへの lstat(2) または fstatat(2) 実施 O 計測結果 O 1000 回繰り返し時に 6 ~ 7 秒の違い O lstat(2) と fstatat(2) のコスト差は 1階層あたり 0.6 usec ~ 0.7 usec
  28. 28. 性能計測の評価 O 対象10,000超で体感的な差が出る可能性 O システムコールのコスト差だけでも 対象1,000,000なら数秒オーダーの差 O 実際の環境では、性能劣化要因が増える O ディレクトリ階層が複雑化した場合 ファイル名解決コストの増加 O HDD上のファイルシステムの場合 シーク発生による I/O待ちの増加
  29. 29. 低減策の問題点
  30. 30. 環境毎の仕様準拠 O dirent.d_type による種別情報の提供は POSIX 標準ではオプション扱い O GNU coreutils の ls でも 使用可能な環境では使用 O fstatat(2) の標準化は XPG7 (2013) から O XPG7 非準拠なら、サポートの必要無し (とは言うものの多くの環境で利用可能) O GNU coreutils の ls では未使用
  31. 31. Python からの利用可能性 O Python の標準 API からは dirent.d_type も fstatat(2) も使えない
  32. 32. Python から使えないなら そんな話するな!
  33. 33. そんな時の為の C ライブラリ連携!
  34. 34. Mercurial における listdir() の独自実装
  35. 35. まーきゅりあるノ話ヲ シタイダケデハ ナイデスヨ?(棒)
  36. 36. O ディレクトリ配下要素の 情報取得を行う機能 osutil.listdir() を MercurialではCライブラリとして独自実装 O システムコール実行コストを 環境に応じて極力低減 O DT_REG マクロ判定 (dirent.d_type 利用の可否) O AT_SYMLINK_NOFOLLOW マクロ判定 (fstatat(2) 利用の可否) O Cライブラリ連携を使用できない環境向けに pure Python 版 osutil もあるが 性能的には当然Cライブラリ実装よりも遅い
  37. 37. 結論
  38. 38. ls.c は読まなくても…. O mercurial/osutil.c の listdir() 実装は 読んでおいた方が良いかもね! O ディレクトリ要素や要素毎情報の取得で 使用している API を把握しよう O API 使い分けによる 性能への影響を理解しよう O POSIX環境向けと Windows環境向け実装が 同一ファイル中にあるので参照時は注意
  39. 39. Pythonista も…. O 「lsを読まずにプログラマを名乗るな!」を 買ってね! O OS の内部処理とかファイルシステム周りの 話も盛り込んであるよ!
  40. 40. 参考資料
  41. 41. Mercurial O プロジェクトページ http://mercurial.selenic.com/ O mercurial/osutil.c http://selenic.com/repo/hg/file/stable/mercurial/osutil.c O mercurial/pure/osutil.py http://selenic.com/repo/hg/file/stable/mercurial/pure/osutil.py
  42. 42. POSIX仕様 O XPG6: IEEE Std 1003.1, 2004 Edition http://pubs.opengroup.org/onlinepubs/9699919799/ O XPG7: IEEE Std 1003.1, 2013 Edition http://pubs.opengroup.org/onlinepubs/009695399/
  43. 43. GNU coreutils O プロジェクトページ http://www.gnu.org/software/coreutils/ O src/ls.c http://git.savannah.gnu.org/cgit/coreutils.git/tree/src/ls.c
  44. 44. 「lsを読まずに プログラマを名乗るな!」 O 書籍情報 http://www.shuwasystem.co.jp/products/7980html/3943.html O サポートページ http://www.lares.dti.ne.jp/~foozy/fujiguruma/ls-src/index.html
  45. 45. おしまい
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×