2011-11-07 10 views
5

Bir dosyada kaç satır bulunduğunu okumak için performansı karşılaştırıyorum. Ben daha hızlı olması için Smalltalk kod hızlandırabilir Nasıl temiz bir Pharo Çekirdek Smalltalk son 1,3Yeni satır sayılarını karşılaştırmak wc ve Smalltalk arasındaki hızı

| 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 

sonra

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

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

ve:

Ben ilk wc komut satırı aracını kullanarak yaptım veya wc performansından daha mı yakın?

cevap

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

yukarıdaki raporlar ~ 207 sefer bildirilen milisaniye: Şaka yapıyorum

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

değil, aynı zamanda ciddi. Tekerleği yeniden icat etmeye gerek yok. FFI, OSProcess, Zinc, vb. Onlarca yıldır savaş testine tabi tutulan UNIX yardımcı programları gibi şeyleri kullanmak için geniş bir fırsat sunmaktadır. Sorunuzun Smalltalk kendisi hakkında gerçekten daha olsaydı

, bir başlangıç ​​olacaktır:

  • ~ 10 saniye
  • kaydedilmiş akışı ikili yapma:

    [ 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. 
    

    Yani 2,5 saniye aşağı alırsınız

  • readOnlyFileNamed: do: kaydedilen ~ 1 saniye
  • Satır sonlarını el ile bulmak yerine #nextLine kaydedildi ~ 4 saniye

bir temizleyici, ancak 1/2 saniyeden daha uzun op olacaktır: Daha iyi performans gerekiyorsa Tabii

file contents occurrencesOf: 10.

, ve FFI/OSProcess kullanmak istemiyorum, olur daha sonra bir eklenti yazınız. Eğer bellekteki dosyanın tamamını okuma gelemez

+0

Bahse girerim Kodunuzdaki en büyük tasarruf, dosyayı ikili yapmaktan değil, tüm içeriği "içerikler" kullanarak işlenmeden önce belleğe okumadan gelmez. Dosyayı makul boyuttaki parçalarda okumak, yaklaşık aynı şeyi yapmalıdır. –

+0

İki kez kontrol ettim ... #binary aslında #asciiValue çağırmak veya "Karakter lf" ile karşılaştırmak için 10 saniye kaydedildi (bir sıcaklıkta önbelleğe alınsa bile). #contents, #next ile manuel döngüye karşılık 3.5 saniyede kaydedildi. –

1

ardından en basit kod

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

Bu LF (Linux), CR (Eski Mac), CR-LF (size isminin hayvanat bahçesi idare edecek olan o). Sean'ın kodu, yaklaşık olarak aynı maliyet için yalnızca LF'yi kullanıyor. Smalltalk vs C'nin bu gibi temel işlemler için bir faktör 10 olması bekleniyor, bu yüzden kendi ilkellerinizi eklemeden çok daha fazla verim aldığınızdan şüpheliyim.

İlgili konular