¿Cómo puedo cortar y cortar rápidamente los archivos de datos grandes?


5

Me gustaría cortar y dar grandes archivos de datos, hasta un concierto, de una manera bastante rápida y eficiente. Si utilizo algo como "CUT" de UNIX, es extremadamente rápido, incluso en un entorno CYGWIN.

He intentado desarrollar y comparar varios scripts de Ruby para procesar estos archivos, y siempre acabo obteniendo resultados glaciales.

¿Qué harías en Ruby para que esto no sea tan lento?

1

Por qué no combinarlos juntos - con ayuda de corte para hacer lo que es mejor y el rubí hace para proporcionar el pegamento/valor agregado con los resultados de la CUT? puede ejecutar scripts de shell al ponerlos en backticks como este:

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

en lugar de escribir en un archivo temporal, puede hacer: pipe = IO.popen ("cortar ..."); pipe.each_line {| línea | ...} 29 jul. 092009-07-29 16:22:34


2

Esta pregunta me recuerda a Tim Bray's Wide Finder project. La forma más rápida que podía leer un archivo de registro de Apache usando Ruby y averiguar qué artículos han sido extraídas de la mayoría era con este 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 

Tomó el código 7 ½ segundos de CPU, 13½ segundos transcurridos, al proceso de un millón y cambio de registros, un cuarto de concierto más o menos, en el PowerBook de 1.67Ghz del año pasado.


1

Supongo que las implementaciones de Ruby están leyendo todo el archivo antes del procesamiento. El corte de Unix funciona leyendo cosas de un byte a la vez y inmediatamente volcando a un archivo de salida. Por supuesto, hay algo de buffer involucrado, pero no más de unos pocos KB.

Mi sugerencia: intente hacer el procesamiento en el lugar con la menor paginación o retroceso posible.


0

Dudo que el problema es que Ruby está leyendo todo el archivo en la memoria. Observe la memoria y el uso del disco mientras ejecuta el comando para verificar.

Supongo que la razón principal es porque el corte está escrito en C y solo está haciendo una cosa, por lo que probablemente se haya compilado hasta el mismo metal. Probablemente no esté haciendo mucho más que llamar al sistema.

Sin embargo, la versión de ruby ​​hace muchas cosas a la vez. Llamar a un método es mucho más lento en ruby ​​que las llamadas a función C.

Recuerde vejez y trechery vencieron a la juventud y la habilidad en UNIX: http://ridiculousfish.com/blog/archives/2006/05/30/old-age-and-treachery/