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