Come faccio a tagliare e tagliare velocemente file di dati di grandi dimensioni?


5

Mi piacerebbe tagliare e tagliare file di dati di grandi dimensioni, fino a un concerto, in modo abbastanza rapido ed efficiente. Se uso qualcosa come "CUT" di UNIX, è estremamente veloce, anche in un ambiente CYGWIN.

Ho provato a sviluppare e confrontare vari script Ruby per elaborare questi file, e sempre finiscono con risultati glaciali.

Cosa faresti in Ruby per rendere questo non così lento?

1

perché non combinare insieme - con taglio a fare quello che sa fare meglio e rubino per fornire il collante/a valore aggiunto con i risultati di CUT? è possibile eseguire script di shell inserendoli in apici inversi in questo modo:

puts `cut somefile > foo.fil` 
# process each line of the output from cut 
f = File.new("foo.fil") 
f.each{|line| 
} 
+1

piuttosto che scrivere in un file temporaneo, si potrebbe fare: pipe = IO.popen ("cut ..."); pipe.each_line {| line | ...} 29 lug. 092009-07-29 16:22:34


2

Questa domanda mi ricorda Tim Bray Wide Finder project. Il modo più veloce che poteva leggere un file di log di Apache con Ruby e capire quali articoli sono stati prelevato il più è stato con questo script:

counts = {} 
counts.default = 0 

ARGF.each_line do |line| 
    if line =~ %r{GET /ongoing/When/\d\d\dx/(\d\d\d\d/\d\d/\d\d/[^ .]+) } 
    counts[$1] += 1 
    end 
end 

keys_by_count = counts.keys.sort { |a, b| counts[b] <=> counts[a] } 
keys_by_count[0 .. 9].each do |key| 
    puts "#{counts[key]}: #{key}" 
end 

Ha preso questo codice 7½ secondi di CPU, 13½ secondi trascorsi, a processo un milione e cambia i record, un quarto d'ora circa, sul PowerBook di 1,67 Ghz dell'anno scorso.


1

Immagino che le implementazioni di Ruby stiano leggendo l'intero file prima dell'elaborazione. Il taglio di Unix funziona leggendo le cose un byte alla volta e immediatamente dumping in un file di output. C'è ovviamente del buffering, ma non più di qualche KB.

Il mio suggerimento: prova a eseguire l'elaborazione sul posto con il minor numero possibile di impaginazioni o backtracking.


0

Dubito che il problema sia che Ruby sta leggendo l'intero file in memoria. Guarda la memoria e l'utilizzo del disco mentre esegui il comando per verificare.

Immagino che il motivo principale sia perché il taglio è scritto in C e sta facendo solo una cosa, quindi probabilmente è stato compilato proprio sul metallo. Probabilmente non sta facendo molto di più che chiamare le chiamate di sistema.

Tuttavia la versione in rubino sta facendo molte cose contemporaneamente. Chiamare un metodo è molto più lento nel rubino rispetto alle chiamate di funzione C.

Ricordate la vecchiaia e la trechery battere la gioventù e l'abilità in UNIX: http://ridiculousfish.com/blog/archives/2006/05/30/old-age-and-treachery/