Próbuję przeprowadzić test porównawczy, aby porównać dwa różne sposoby przetwarzania pliku. Mam niewielką ilość danych wejściowych, ale aby uzyskać dobre porównania, muszę kilkakrotnie powtórzyć testy.
Zamiast po prostu powtarzać testy, chciałbym zduplikować dane wejściowe kilka razy (np. 1000), aby plik z 3 liniami zamienił się w 3000 linii i mógłbym przeprowadzić test o wiele bardziej satysfakcjonujący.
Przesyłam dane wejściowe przez nazwę pliku:
mycommand input-data.txt
perl
jest tak wydajny, że jest przeznaczony do tego.Początkowo myślałem, że będę musiał wygenerować plik pomocniczy, ale mogę po prostu zapętlić oryginalny plik w Bash i użyć przekierowania, aby pojawił się jako plik.
Prawdopodobnie istnieje kilkanaście różnych sposobów wykonania pętli, ale oto cztery:
Trzecia metoda jest improwizowana na podstawie komentarza maru poniżej i buduje dużą listę nazw plików wejściowych dla cat.
xargs
podzieli to na tyle argumentów, na ile pozwoli system. Jest znacznie szybszy niż n osobnych kotów.awk
Sposób (zainspirowany odpowiedź terdon za ) jest prawdopodobnie najbardziej zoptymalizowane, ale powiela każdą linię naraz. To może, ale nie musi pasować do konkretnego zastosowania, ale jest błyskawiczne i wydajne.Ale to generuje w locie. Wyprowadzanie basha prawdopodobnie będzie znacznie wolniejsze niż coś, co można odczytać, więc powinieneś wygenerować nowy plik do testowania. Na szczęście to tylko bardzo proste rozszerzenie:
źródło
cat $(for i in {1..N}; do echo filename; done)
. Ma to ograniczenie wielkości arg, ale powinno być szybsze.Oto
awk
rozwiązanie:Jest w zasadzie tak szybki jak Perl @ Gnuca (biegnąłem zarówno 1000 razy, jak i dostałem średni czas):
źródło
awk '{for(i=0; i<1000; i++)print}' input-data.txt
tak aby po prostu wydawało 1000 kopii każdej linii na raz. Nie będzie pasować na wszystkie okazje, ale nawet szybciej, mniej opóźnień i nie trzeba przechowywać całego pliku w pamięci RAM.123123123
było dobrze, ale111222333
nie było. Twoja wersja jest wyraźnie szybsza niż Gnouc, średnio 0,00297 sekundy. EDYCJA: podrap, że popełniłem błąd, w rzeczywistości jest to równowartość 0,004013 sekund.Chciałbym po prostu użyć edytora tekstu.
Jeśli absolutnie musisz to zrobić za pomocą wiersza polecenia (wymaga to
vim
zainstalowania, ponieważvi
nie ma:normal
polecenia), możesz użyć:Tutaj
-es
(lub-e -s
) sprawia, że vim działa cicho, więc nie powinien przejmować okna terminala i-u NONE
powstrzymuje go od patrzenia na vimrc, co powinno sprawić, że będzie działał trochę szybciej niż w innym przypadku (może znacznie szybciej, jeśli użyjesz dużo wtyczek vima).źródło
Oto prosty linijka, bez skryptów:
Wyjaśnienie
`yes input-data.txt | head -1000 | paste -s`
tworzy tekstinput-data.txt
1000 razy oddzielony białym odstępemcat
postaci listy plikówźródło
xargs paste -s
? Działa to, ale nie zachowuje nowych linii w pliku wejściowym.Pracując nad zupełnie innym skryptem, dowiedziałem się, że przy 29 milionach wierszy tekstu używanie
seek()
i działanie na danych jest często szybsze niż w przypadku poszczególnych linii. Ten sam pomysł zastosowano w skrypcie poniżej: otwieramy plik i zamiast przechodzić przez pętlę poprzez otwieranie i zamykanie pliku (co może zwiększać obciążenie, nawet jeśli nie jest znaczące), utrzymujemy plik otwarty i wracamy do początku.Sam skrypt jest dość prosty w użyciu:
W przypadku 3-wierszowego pliku tekstowego i iteracji 1000 idzie całkiem dobrze, około 0,1 sekundy:
Sam skrypt nie jest najbardziej elegancki, prawdopodobnie można go skrócić, ale spełnia swoje zadanie. Oczywiście dodałem tu i tam kilka dodatkowych bitów, takich jak
error_out()
funkcja, która nie jest konieczna - to tylko mały, przyjazny dla użytkownika dotyk.źródło
Możemy to rozwiązać bez dodatkowego pliku, ani specjalnych programów, czysto Bash (cóż, cat to standardowe polecenie).
W oparciu o funkcję printf w bash możemy wygenerować powtarzający się ciąg):
Następnie możemy wysłać taką listę 1000 nazw plików (powtórzonych) i wywołać cat:
Na koniec możemy podać dane wyjściowe polecenia, aby wykonać:
Lub, jeśli polecenie musi otrzymać dane wejściowe w standardowym wejściu:
Tak, potrzebne jest podwójne <.
źródło
Wygenerowałbym nowy plik przy użyciu Uniksa dla pętli:
źródło