2011-11-07 5 views
5

ファイルを含む行の数を読み込むパフォーマンスを比較しています。私は速いとSmalltalkのコードをスピードアップすることができますどのようにきれいなファロコアSmalltalkの最新1.3wcとSmalltalkの間の改行数の速度を比較する

| 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 

で、その後

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

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

と:

は、私はそれが最初のWCコマンドラインツールを使用していましたwcの性能よりも近いか?

答えて

8
[ (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の自分自身について本当に以上であった場合

は、開始は次のようになります。

2.5秒まであなたを取得します
[ 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. 

  • 〜10秒保存されたストリームのバイナリを作る
  • readOnlyFileNamed:do:saved〜1 second
  • #nextLineを保存する代わりに手作業で行末を検索する〜4秒

クリーナー、しかし1/2秒より長くOPは次のよ​​うになります。より良いパフォーマンスが必要な場合は、

もちろん

file contents occurrencesOf: 10.

、そしてあなたがFFI/OSProcessを使用したくない、あなたはでしょうプラグインを作成します。

+0

私はあなたのコードで最大の節約は、ファイルのバイナリを作ることから来るのではなく、 "コンテンツ"を使用して処理する前にファイル全体をメモリから読み込むことによると思います。合理的なサイズのチャンクでファイルを読むことは、同じことをする必要があります。 –

+0

#binaryは#asciiValueを呼び出したり、 "Character lf"(たとえtempにキャッシュされていても)と比較して実際に10秒保存しました。 #contentsは#nextを使用した手動ループと3.5秒の間に保存されました。 –

1

あなたはメモリ内のファイル全体を読み込む余裕がある場合は、最も簡単なコードはこれはLF(Linuxの)、CR(旧マック)、CR-LF(あなたの名前の動物園を処理する

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

ですそれ)。 Seanのコードは、ほぼ同じコストでLFのみを処理します。 Smalltalk vs Cのような基本的な操作には10倍の要素が必要だと思いますので、独自のプリミティブを追加することなく効率を上げることはできません。

関連する問題