2016-04-23 13 views
1

ストリームをフィルタとして処理する(つまり、ビットを取得する、プロセスをリンスする)、スラップする(つまり、すべての情報を取得してから処理する)ことに対する効果を比較したいと思います。Pythonでファイルを読む:slurpまたはfilter?

ただし、以下の2つのコードを実行すると、同等の結果が得られます。私はslurpバージョンではるかに悪い結果を得ることを期待していた。

以下のコードスニペットは、上記のように異なる処理を行っていますか?それらが同等であれば、どのようにフィルタ/スラップの差をテストするためにそれらの1つを適合させることができますか?

私は、スクリプトをテストしていた。

jot 100000000 | time python3 dont_slurp.py > /dev/null 
jot 100000000 | time python3 slurp.py > /dev/null 

Jotは1からのxに番号を生成します。コードスニペットは行を数値化するだけです。

フィルタ:

import sys 
lineno = 0 
for line in sys.stdin: 
    lineno += 1 
    print("{:>6} {}".format(lineno, line[:-1])) 

SLURP:すべての

import sys 

f = sys.stdin 
lineno = 0 

for line in f: 
    lineno += 1 
    print('{:>6} {}'.format(lineno, line[:-1])) 
+2

「Slurp」バージョンは、あなたが思う通りのことをしていません。どちらのバージョンも一度に1行ずつ読み込んでいます。すべての行を一度に読むには 'for line in f.readlines()'を実行します。 –

答えて

0

まず、あなたのコードサンプルは、あなたが何を考えてやっていません。 f = sys.stdinはすべてfと同じファイルハンドルに設定されています。 for line in f:for line in sys.stdin:の行は機能的に同一です。

は何が欲しいのはこれです:

import sys 

lineno = 0 

for line in sys.stdin.readlines(): 
     lineno += 1 
     print('{:>6} {}'.format(lineno, line[:-1])) 

readlines()は、リスト、ファイル内の1行に1つの要素を返します。私はそれがではないと信じて、ジェネレータ、あなたは完全なリストを取得します。ファイルハンドル自体はジェネレータとして機能し、一度に1行ずつ与えられます。

パフォーマンス差異はreadline()と表示されます。

しかし、「これは良いですか? 「それは依存する」。 1行ずつ読むと、システムコールが実行されます。その結果、OSはファイルの内容をブロック単位でディスクから読み込みます。これらのブロックは平均ラインのサイズよりも大きい可能性が高く、ブロックはキャッシュされている可能性があります。これは、ディスクにヒットしたり、時間がかかったり、キャッシュにヒットしたり、時間がかかったりすることもあります。

すべてを一度に読み取ると、ファイルからメモリに一度にすべてのバイトが読み込まれます。すべてのファイルの内容を保持するのに十分な空きメモリがある場合は、行単位のバージョンとまったく同じ時間がかかります。どちらの場合も、基本的には少しオーバーヘッドでファイル全体を順番に読み取るのに必要な時間です。

違いは、ファイル全体を保持するのに十分な空きメモリがない場合です。その場合、ファイル全体を読み込みますが、その一部は仮想メモリシステムによってディスクにスワップアウトされます。あなたはその特定の行にアクセスするときに再び取り込まなければなりません。

どのくらいの時間のメモリが使用されているか、他のアクティビティがシステム上でどのくらい行われているかなどによって、どれくらい時間が失われるかは、一般的には定量化できません。

問題が発生するまで正直に心配する必要はありません。コード内で自然なことを行い、プログラムが遅すぎる場合はパフォーマンスについて心配してください。

+0

私が指摘する価値があるかもしれないもう一つのポイントは、フィルタリングをすれば、I/OとCPUの作業を並行して行うことができるかもしれないということです。 –

関連する問題