6

ファイルが含まれている行数を読み取るためのパフォーマンスを比較しています。

私は最初にwcコマンドラインツールを使用してそれを行いました:

$ time wc -l bigFile.csv
1673820 bigFile.csv

real    0m0.157s
user    0m0.124s
sys     0m0.062s

そして、クリーンなPharoCoreSmalltalk最新1.3で

| file lineCount |
Smalltalk garbageCollect.
( Duration milliSeconds: [ file := FileStream readOnlyFileNamed: 'bigFile.csv'.
lineCount := 0.
[ file atEnd ] whileFalse: [
    file nextLine.
    lineCount := lineCount + 1 ].
file close.
lineCount. ] timeToRun ) asSeconds. 
15

Smalltalkコードを高速化して、wcのパフォーマンスよりも速くまたは近づけるにはどうすればよいですか?

4

2 に答える 2

9
[ (PipeableOSProcess waitForCommand: 'wc -l /path/to/bigfile2.csv') output ] timeToRun.

上記は約207ミリ秒を報告し、時間は次のように報告されます。

real    0m0.160s
user    0m0.131s
sys     0m0.029s

冗談ですが、真面目です。車輪の再発明をする必要はありません。FFI、OSProcess、Zincなどは、数十年にわたってバトルテストが行​​われているUNIXユーティリティなどを利用する十分な機会を提供します。

あなたの質問が本当にSmalltalk自体についてだったとしたら、最初は次のようになります。

[ FileStream 
    readOnlyFileNamed: '/path/to/reallybigfile2.csv'
    do: [ :file | | endings count |
        count := 0.
        file binary.
        file contents do: [ :c | c = 10 ifTrue: [ count := count + 1 ] ].
        count ]
] timeToRun.

これで2.5秒になります。

  • ストリームバイナリを最大10秒節約
  • readOnlyFileNamed:do:約1秒節約
  • #nextLineを使用する代わりに、行末を手動で検索すると、約4秒節約できます

よりクリーンですが、1/2秒長い操作は次のようになります。

file contents occurrencesOf: 10.

もちろん、より良いパフォーマンスが必要で、FFI / OSProcessを使用したくない場合は、プラグインを作成します。

于 2011-11-07T20:10:50.273 に答える
2

メモリ内のファイル全体を読み取る余裕がある場合、最も単純なコードは次のとおりです。

[ FileStream 
    readOnlyFileNamed: '/path/to/reallybigfile2.csv'
    do: [ :file | file contents lineCount ]
] timeToRun.

これは、LF(Linux)、CR(Old Mac)、CR-LF(名前を付けます)の動物園を処理します。Seanのコードは、ほぼ同じコストでLFのみを処理します。このような基本的な操作では、Smalltalk vs Cの係数10が期待されると思います。したがって、独自のプリミティブを追加しなくても、はるかに効率が上がるとは思えません。

于 2012-06-04T12:35:24.373 に答える