Cóż Zgodnie z komentarzem do odpowiedzi shuf przetasował 78 000 000 000 linii w niecałą minutę.
Wyzwanie przyjęte...
Najpierw potrzebowałem pliku 78.000.000.000 linii:
seq 1 78 | xargs -n 1 -P 16 -I% seq 1 1000 | xargs -n 1 -P 16 -I% echo "" > lines_78000.txt
seq 1 1000 | xargs -n 1 -P 16 -I% cat lines_78000.txt > lines_78000000.txt
seq 1 1000 | xargs -n 1 -P 16 -I% cat lines_78000000.txt > lines_78000000000.txt
To daje mi plik z 78 miliardami nowych linii ;-)
Teraz część shuf:
$ time shuf -n 10 lines_78000000000.txt
shuf -n 10 lines_78000000000.txt 2171.20s user 22.17s system 99% cpu 36:35.80 total
Wąskim gardłem był procesor i nie używający wielu wątków, przypiął 1 rdzeń na 100%, a pozostałych 15 nie było używanych.
Python jest tym, czego regularnie używam, więc tego użyję, aby przyspieszyć:
#!/bin/python3
import random
f = open("lines_78000000000.txt", "rt")
count = 0
while 1:
buffer = f.read(65536)
if not buffer: break
count += buffer.count('\n')
for i in range(10):
f.readline(random.randint(1, count))
To dało mi niecałą minutę:
$ time ./shuf.py
./shuf.py 42.57s user 16.19s system 98% cpu 59.752 total
Zrobiłem to na Lenovo X1 Extreme 2. generacji z i9 i Samsung NVMe, co daje mi dużą prędkość odczytu i zapisu.
Wiem, że może być szybciej, ale zostawię trochę miejsca, aby dać innym szansę.
Źródło licznika linii : Luther Blissett