Posterior a de una larga búsqueda de datos dimos con la solución esta contratiempo que tienen muchos de nuestros usuarios. Te dejamos la solución y nuestro objetivo es serte de mucha apoyo.
Solución:
Get-Content
es terriblemente ineficaz para leer archivos grandes. Sort-Object
no es muy rápido, también.
Establezcamos una línea base:
$sw = [System.Diagnostics.Stopwatch]::StartNew();
$c = Get-Content .log3.txt -Encoding Ascii
$sw.Stop();
Write-Output ("Reading took 0" -f $sw.Elapsed);
$sw = [System.Diagnostics.Stopwatch]::StartNew();
$s = $c | Sort-Object;
$sw.Stop();
Write-Output ("Sorting took 0" -f $sw.Elapsed);
$sw = [System.Diagnostics.Stopwatch]::StartNew();
$u = $s | Get-Unique
$sw.Stop();
Write-Output ("uniq took 0" -f $sw.Elapsed);
$sw = [System.Diagnostics.Stopwatch]::StartNew();
$u | Out-File 'result.txt' -Encoding ascii
$sw.Stop();
Write-Output ("saving took 0" -f $sw.Elapsed);
Con un archivo de 40 MB que tiene 1,6 millones de líneas (compuesto por 100k líneas únicas repetidas 16 veces), este script produce el siguiente resultado en mi máquina:
Reading took 00:02:16.5768663
Sorting took 00:02:04.0416976
uniq took 00:01:41.4630661
saving took 00:00:37.1630663
Totalmente impresionante: más de 6 minutos para ordenar un archivo pequeño. Cada paso se puede mejorar mucho. usemos StreamReader
para leer el archivo línea por línea en HashSet
que eliminará los duplicados, luego copiará los datos a List
y ordenarlo allí, luego usar StreamWriter
para volcar los resultados.
$hs = new-object System.Collections.Generic.HashSet[string]
$sw = [System.Diagnostics.Stopwatch]::StartNew();
$reader = [System.IO.File]::OpenText("D:log3.txt")
try
while (($line = $reader.ReadLine()) -ne $null)
$t = $hs.Add($line)
finally
$reader.Close()
$sw.Stop();
Write-Output ("read-uniq took 0" -f $sw.Elapsed);
$sw = [System.Diagnostics.Stopwatch]::StartNew();
$ls = new-object system.collections.generic.List[string] $hs;
$ls.Sort();
$sw.Stop();
Write-Output ("sorting took 0" -f $sw.Elapsed);
$sw = [System.Diagnostics.Stopwatch]::StartNew();
try
$f = New-Object System.IO.StreamWriter "d:result2.txt";
foreach ($s in $ls)
$f.WriteLine($s);
finally
$f.Close();
$sw.Stop();
Write-Output ("saving took 0" -f $sw.Elapsed);
este script produce:
read-uniq took 00:00:32.2225181
sorting took 00:00:00.2378838
saving took 00:00:01.0724802
En el mismo archivo de entrada, se ejecuta más de 10 veces más rápido. Todavía estoy sorprendido, aunque se tarda 30 segundos en leer el archivo del disco.
Sección de Reseñas y Valoraciones
Acuérdate de que puedes optar por la opción de agregar una reseña si te ayudó.