pythonista も ls を読むべきか?

47
Pythonista ls を読むべきか? 藤原 克則 @flyingfoozy

Upload: katsunori-fujiwara

Post on 24-May-2015

4.046 views

Category:

Technology


3 download

DESCRIPTION

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

TRANSCRIPT

Page 1: Pythonista も ls を読むべきか?

Pythonista も ls を読むべきか?

藤原 克則 @flyingfoozy

Page 2: Pythonista も ls を読むべきか?

自己紹介

Page 3: Pythonista も ls を読むべきか?

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 を読むべきか?

O 分散リポジトリ型履歴管理ツール Mercurial の翻訳コミッタ/コントリビュータ

O Mercurial の hack に特化した なんちゃって Pythonista

Page 5: Pythonista も ls を読むべきか?
Page 6: Pythonista も ls を読むべきか?

O Solaris 上で稼働させる HPC 向けファイルシステムの実装などを 仕事でやっていたことも

O 「Tokyo OpenSolaris 勉強会」 で Solarisカーネルの実装に関する勉強とか http://www.opensolaris.gr.jp/study.html

O 下位レイヤの話も好き

Page 7: Pythonista も ls を読むべきか?
Page 8: Pythonista も ls を読むべきか?

執筆過程で見つけた バグの修正パッチが

ソースツリーに取り込まれた

Page 9: Pythonista も ls を読むべきか?

GNU coreutils の ls は ワシが育てた! (約1/4900)

Page 10: Pythonista も ls を読むべきか?

本日のお題は….

Page 11: Pythonista も ls を読むべきか?

Pythonista も ls を読むべきか?

Page 12: Pythonista も ls を読むべきか?

Pythonista: 「os.listdir() を使うから 読まなくても良くねぇ?」

Page 13: Pythonista も ls を読むべきか?

例えばこんな感じ?

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 を読むべきか?

そんな実装では スケールしない!!!

Page 15: Pythonista も ls を読むべきか?

システムコール 呼び出しコスト

O os.path.isdir(), os.path.isfile() ... は 判定処理毎に lstat(2) 呼び出し

O 呼び出し頻度は 「要素数 × 平均的な if 判定数」

O コンテキストスイッチを生じるので 通常の関数呼び出しよりも 圧倒的にコストが高い

Page 16: Pythonista も ls を読むべきか?

多少コスト意識が ある場合は….

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 を読むべきか?

それでも残る 性能劣化要因

Page 18: Pythonista も ls を読むべきか?

要因 (1) ~ os.lstat() 呼び出しコスト

O os.listdir() は 内部的に readdir(3) を使用

O readdir(3) が返す struct dirent は 要素種別情報 d_type を保持

O 種別情報のみで事足りる場合 os.lstat() 呼び出し自体が不要な筈 (サイズや日時情報が必要ない場合等)

Page 19: Pythonista も ls を読むべきか?

要因 (2) ~ ファイル名解決コスト

O OS内部でのファイル名解決 (ファイル名⇒対象の管理情報)は パス要素毎の繰り返し処理で実現

O os.lstat() に指定されるファイル名にも 同様の解決コストが必要

Page 20: Pythonista も ls を読むべきか?

“foo/bar/baz/file” に対する OS内部でのファイル名解決例

1. “.” への “foo” の問い合わせ

2. “./foo" 相当の管理情報の取得

3. “./foo” への “bar” の問い合わせ

4. “./foo/bar” 相当の管理情報の取得

5. “./foo/bar” への .......

Page 21: Pythonista も ls を読むべきか?

ファイル名解決における 直接的なコスト

O ディレクトリ階層の深さ ⇒ 繰り返しによるコストの高低

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

(名前解決キャッシュ/木構造管理/ハッシュテーブル)

O 運用回避 e.g.ディレクトリ配下の要素数に上限を設ける (proxyサーバやブラウザのキャッシュ)

Page 22: Pythonista も ls を読むべきか?

ファイル名解決における 間接的なコスト

O 階層/配下要素の増加による I/O 量の増加

O メモリアクセスと比べて、 圧倒的にコストが高い

O I/O 対象の散在によるシークコストの増加

O 記録媒体が HDD であれば、 ミリ秒単位の I/O 待ち状態

O GHz クラスの CPU なら、 単純計算でも百万命令単位分の I/O 待ち

Page 23: Pythonista も ls を読むべきか?

性能劣化の低減策

Page 24: Pythonista も ls を読むべきか?

低減策 (1) ~ os.lstat() 呼び出しの低減

O readdir(3) が返す struct dirent には 各要素の種別情報を保持する d_type フィールドがある

O 種別情報のみで事足りるなら lstat(2) 呼び出し自体が不要

Page 25: Pythonista も ls を読むべきか?

低減策 (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 を読むべきか?

低減策の効果計測

Page 27: Pythonista も ls を読むべきか?

基本条件

O 1.8GHz 4 core Atom 環境

O I/O 要因での性能劣化を極力防止

O メモリファイルシステム上でテスト

O 常に現ディレクトリからの相対アクセス

O 必要なファイル/ディレクトリ要素のみ

Page 28: Pythonista も ls を読むべきか?

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 を読むべきか?

ファイル名解決のコスト

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 を読むべきか?

性能計測の評価

O 対象10,000超で体感的な差が出る可能性

O システムコールのコスト差だけでも 対象1,000,000なら数秒オーダーの差

O 実際の環境では、性能劣化要因が増える

O ディレクトリ階層が複雑化した場合 ファイル名解決コストの増加

O HDD上のファイルシステムの場合 シーク発生による I/O待ちの増加

Page 31: Pythonista も ls を読むべきか?

低減策の問題点

Page 32: Pythonista も ls を読むべきか?

環境毎の仕様準拠

O dirent.d_type による種別情報の提供は POSIX 標準ではオプション扱い

O GNU coreutils の ls でも 使用可能な環境では使用

O fstatat(2) の標準化は XPG7 (2013) から

O XPG7 非準拠なら、サポートの必要無し (とは言うものの多くの環境で利用可能)

O GNU coreutils の ls では未使用

Page 33: Pythonista も ls を読むべきか?

Python からの利用可能性

O Python の標準 API からは dirent.d_type も fstatat(2) も使えない

Page 34: Pythonista も ls を読むべきか?

Python から使えないなら そんな話するな!

Page 35: Pythonista も ls を読むべきか?

そんな時の為の C ライブラリ連携!

Page 36: Pythonista も ls を読むべきか?

Mercurial における listdir() の独自実装

Page 37: Pythonista も ls を読むべきか?

まーきゅりあるノ話ヲ シタイダケデハ ナイデスヨ?(棒)

Page 38: Pythonista も ls を読むべきか?

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 を読むべきか?

結論

Page 40: Pythonista も ls を読むべきか?

ls.c は読まなくても….

O mercurial/osutil.c の listdir() 実装は 読んでおいた方が良いかもね!

O ディレクトリ要素や要素毎情報の取得で 使用している API を把握しよう

O API 使い分けによる 性能への影響を理解しよう

O POSIX環境向けと Windows環境向け実装が 同一ファイル中にあるので参照時は注意

Page 41: Pythonista も ls を読むべきか?

Pythonista も….

O 「lsを読まずにプログラマを名乗るな!」を 買ってね!

O OS の内部処理とかファイルシステム周りの話も盛り込んであるよ!

Page 42: Pythonista も ls を読むべきか?

参考資料

Page 43: Pythonista も ls を読むべきか?

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 を読むべきか?

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 を読むべきか?

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 を読むべきか?

「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 を読むべきか?

おしまい