Ich versuche ein Benchmarking durchzuführen, um zwei verschiedene Arten der Dateiverarbeitung zu vergleichen. Ich habe eine kleine Menge von Eingabedaten, aber um gute Vergleiche zu erhalten, muss ich die Tests einige Male wiederholen.
Anstatt nur die Tests zu wiederholen, möchte ich die Eingabedaten mehrmals duplizieren (z. B. 1000), damit eine Datei mit 3 Zeilen zu 3000 Zeilen wird und ich einen viel ausführlicheren Test ausführen kann.
Ich übergebe die Eingabedaten über einen Dateinamen:
mycommand input-data.txt
perl
ist es so effizient, dass es dafür ausgelegt ist.Ich dachte ursprünglich, dass ich eine sekundäre Datei generieren müsste, aber ich könnte einfach die ursprüngliche Datei in Bash schleifen und eine Umleitung verwenden, um sie als Datei erscheinen zu lassen.
Es gibt wahrscheinlich ein Dutzend verschiedene Möglichkeiten, die Schleife auszuführen, aber hier sind vier:
Die dritte Methode, die es gibt, ist aus Marus Kommentar unten improvisiert und erstellt eine große Liste von Eingabedateinamen für cat.
xargs
wird dies in so viele Argumente aufteilen, wie das System zulässt. Es ist viel schneller als n separate Katzen.Der
awk
Weg (inspiriert von Terdons Antwort ) ist wahrscheinlich der optimierteste, aber er dupliziert jede Zeile gleichzeitig. Dies kann für eine bestimmte Anwendung geeignet sein oder auch nicht, ist jedoch blitzschnell und effizient.Dies wird jedoch im laufenden Betrieb generiert. Die Bash-Ausgabe ist wahrscheinlich sehr viel langsamer als irgendetwas zu lesen ist. Sie sollten daher eine neue Datei zum Testen generieren. Zum Glück ist das nur eine sehr einfache Erweiterung:
quelle
cat $(for i in {1..N}; do echo filename; done)
. Dies hat die Begrenzung der arg-Größe, sollte aber schneller sein.Hier ist eine
awk
Lösung:Es ist im Wesentlichen so schnell wie @ Gnucs Perl (ich habe beide 1000-mal ausgeführt und die durchschnittliche Zeit erhalten):
quelle
awk '{for(i=0; i<1000; i++)print}' input-data.txt
dass nur 1000 Kopien jeder Zeile gleichzeitig ausgegeben werden. Nicht für alle Gelegenheiten geeignet, aber noch schneller, mit weniger Verzögerung und ohne dass die gesamte Datei im RAM gespeichert werden muss.123123123
war es aber111222333
nicht. Ihre Version ist deutlich schneller als die von Gnouc und liegt im Durchschnitt bei 0,00297 Sekunden. BEARBEITEN: Kratz das, ich habe einen Fehler gemacht, es ist eigentlich gleichbedeutend mit 0.004013 Sekunden.Ich würde nur einen Texteditor verwenden.
Wenn Sie dies unbedingt über die Befehlszeile tun müssen (dies setzt voraus, dass Sie
vim
installiert haben, davi
der:normal
Befehl nicht vorhanden ist), können Sie Folgendes verwenden:Hier sorgt
-es
(oder-e -s
) dafür, dass vim im Hintergrund arbeitet, sodass Ihr Terminalfenster nicht-u NONE
überlastet wird , und verhindert, dass Ihr vimrc angezeigt wird. Dies sollte dazu führen, dass vim etwas schneller ausgeführt wird als sonst (möglicherweise viel schneller, wenn Sie es verwenden) viele vim plugins).quelle
Hier ist ein einfacher Einzeiler ohne Scripting:
Erläuterung
`yes input-data.txt | head -1000 | paste -s`
Erzeugt den Textinput-data.txt
1000-mal durch Leerzeichen getrenntcat
als Dateiliste übergebenquelle
xargs paste -s
? Dies funktioniert, behält jedoch keine Zeilenumbrüche in der Eingabedatei bei.Während ich an einem völlig anderen Skript arbeitete, habe ich gelernt, dass mit 29 Millionen Textzeilen das Verwenden
seek()
und Bearbeiten von Daten nacheinander oft schneller ist als nacheinander. Dieselbe Idee wird im folgenden Skript angewendet: Wir öffnen eine Datei, und anstatt die Datei in einer Schleife zu öffnen und zu schließen (was zu zusätzlichem Aufwand führen kann, auch wenn dieser nicht signifikant ist), lassen wir die Datei geöffnet und versuchen, zum Anfang zurückzukehren.Das Skript selbst ist recht einfach zu bedienen:
Für eine 3-zeilige Textdatei und 1000 Iterationen geht es ganz gut, ungefähr 0,1 Sekunden:
Das Drehbuch selbst ist nicht besonders elegant, könnte wahrscheinlich gekürzt werden, macht aber den Job. Natürlich habe ich hier und da ein paar zusätzliche Elemente hinzugefügt, wie z. B. die
error_out()
Funktion, die nicht erforderlich ist - es ist nur eine kleine benutzerfreundliche Berührung.quelle
Wir können dies ohne eine zusätzliche Datei oder spezielle Programme lösen, reine Bash (na ja, cat ist ein Standardbefehl).
Basierend auf einer Funktion von printf in bash können wir einen wiederholten String erzeugen.
Dann können wir eine solche Liste mit 1000 Dateinamen (wiederholt) senden und cat anrufen:
Und schließlich können wir die Ausgabe an den Befehl übergeben, der ausgeführt werden soll:
Oder, wenn der Befehl die Eingabe in der Standardeingabe erhalten muss:
Ja, das double <wird benötigt.
quelle
Ich würde eine neue Datei mit Unix for loop erzeugen:
quelle