Effizient mehrere Zeichen ausgeben

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
JTH
Moderator
Beiträge: 3023
Registriert: 13.08.2008 17:01:41
Wohnort: Berlin

Re: Effizient mehrere Zeichen ausgeben

Beitrag von JTH » 10.05.2019 12:56:00

Python 3 wäre noch eine Möglichkeit:

Code: Alles auswählen

$ time python3 -c'print("#"*100000)'

real	0m0,038s
user	0m0,033s
sys	0m0,005s
Oder Python 2 um drei Zeichen zu sparen:

Code: Alles auswählen

$ time python -c'print"#"*100000'

real	0m0,034s
user	0m0,015s
sys	0m0,016s
Manchmal bekannt als Just (another) Terminal Hacker.

Benutzeravatar
heinz
Beiträge: 535
Registriert: 20.12.2007 01:43:49

Re: Effizient mehrere Zeichen ausgeben

Beitrag von heinz » 11.05.2019 00:16:07

hikaru hat geschrieben: ↑ zum Beitrag ↑
10.05.2019 00:55:03
Vielleicht nicht effizient, aber Brainfuck
Klasse was hier so alles auftaucht! :THX:

Meillo hat geschrieben: ↑ zum Beitrag ↑
10.05.2019 08:18:30
Kannst dir ja mal ueberlegen, ob rueckblickend das Schreiben eines Scriptes...
Habe mir mittlerweile auch einen "zusammengezimmert". Sieht zwar schrecklich aus aber tut was es soll...
Man kann angeben wie oft ein Befehl laufen soll und die Zeiten werden dann gemittelt.
Script: NoPaste-Eintrag40711
Befehlsdatei: NoPaste-Eintrag40715
Ausgabe: NoPaste-Eintrag40716
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.05.2019 08:18:30
Da stimmt die Codezeile noch nicht, oder haben wir uns falsch verstanden?
Habe mich wohl nicht so gut ausgedrueckt.
Die Variante mit yes war schneller als nur dd. (Jetzt weis ich auch warum...)
Deshalb habe ich die an Platz 1 gezeigt.

Da habe ich uebrigens etwas seltsames bei mir festgestellt.
Mit meinem Script kann ich auch die Ausgabe testen, also ob auch wirklich die gewuenschte Menge an Zeichen ausgegeben werden.
Und:

Code: Alles auswählen

yes \#|tr -d '\n'|dd bs=100000 count=1
liefert nicht immer die gewuenschte Menge.
Es werden nur 4096, 8192, 12288, 16384 oder 20480 Zeichen ausgegeben? Wobei ich nicht feststellen/beeinflussen kann wann welche Menge kommt.
Kann das jemand reproduzieren?

Code: Alles auswählen

yes \#|tr -d '\n'|dd bs=1 count=100000
funktioniert immer korrekt.
Liefert yes moeglicherweise nicht schnell genug und dd "denkt" dann da kommt nix mehr?
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.05.2019 08:18:30
Ich denke, am schnellsten waere:
dd bs=100000 count=1 </dev/zero 2>/dev/null | tr \\0 \#
... und nicht eine Variante mit yes(1).
Da hast Du natuerlich Recht. Aber leider nur Platz 3 NoPaste-Eintrag40716
Aber einiges schneller als

Code: Alles auswählen

dd bs=1 count=100000 </dev/zero 2>/dev/null | tr \\0 \#
oder

Code: Alles auswählen

yes \#|head -n 1000000|tr -d '\n'
Meillo hat geschrieben: ↑ zum Beitrag ↑
10.05.2019 08:18:30
printf %.s# {1..100000}
Weil die Shell hier bei der Brace-Expansion eine riesig lange Befehlszeile erzeugen muss
Alles klar, Danke fuer die Aufklaerung.

RobertDebiannutzer hat geschrieben: ↑ zum Beitrag ↑
10.05.2019 09:46:50
Mit "type builtin" kannst Du es herausfinden
Danke fuer den Tipp, wieder was gelernt.

JTH hat geschrieben: ↑ zum Beitrag ↑
10.05.2019 12:56:00
Python wäre noch eine Möglichkeit:
Noch eine Moeglichkeit, super.
Hab ich gleich in die Liste aufgenommen.
Liegt bis jetzt auf Platz 4 NoPaste-Eintrag40716


Die im Moment schnellste Variante scheint

Code: Alles auswählen

perl -e 'print "#"x1000000'
zu sein.
Bisherige Liste: NoPaste-Eintrag40716
(Platz 1 zaehlt nicht, da fehlerhafte ausgabe...)

Gruss, heinz

wanne
Moderator
Beiträge: 7465
Registriert: 24.05.2010 12:39:42

Re: Effizient mehrere Zeichen ausgeben

Beitrag von wanne » 11.05.2019 14:18:01

Die Messungen sind grob unfair: Du misst immer nur den Zeitverbrauch der äußeren bash selbst.
Um das mal zu verdeutlichen:
Ich Poste jetzt nicht das ganze Kommando. Aber ich könnte es euch vorstellen wie es gemeint ist:

Code: Alles auswählen

time echo "##########...#######"
Braucht bei mir zwischen 0.014s und 0.017s während die yes Variante zwischen 0.023s und 0.025s braucht.
Defakto braucht ersteres eigentlich exakt 0s und lediglich mein Terminal (Konsole) ist halt so lahm, dass es die Ausgabe nicht schneller verarbeiten kann. Auf einem xterm bin ich deutlich schneller. (~0.005s)
Kurz nach deiner Messart müsste mein Kommando das rennen Gewinnen, weil es optimal ist.
Daneben sind die 10000 Zeichen halt verdammt wenig. Deswegen müssten die C-Varianten übelst abloosen, weil der gcc gar nicht schnell genug gestartet ist.
rot: Moderator wanne spricht, default: User wanne spricht.

wanne
Moderator
Beiträge: 7465
Registriert: 24.05.2010 12:39:42

Re: Effizient mehrere Zeichen ausgeben

Beitrag von wanne » 11.05.2019 14:28:03

Die Messungen sind grob unfair: Du misst immer nur den Zeitverbrauch der äußeren bash selbst.
Das gilt für das neue Script im im Post vor mir nicht mehr.
rot: Moderator wanne spricht, default: User wanne spricht.

wanne
Moderator
Beiträge: 7465
Registriert: 24.05.2010 12:39:42

Re: Effizient mehrere Zeichen ausgeben

Beitrag von wanne » 11.05.2019 15:52:46

Hier ein etwas erweitertes Script: pastebin/?mode=view&s=40718
* Anzahl der # kan ausgewählt werden
* Hash statt Dateigröße wird verglichen
* Deafault auf builtin time gesetzt
* mktmp genutzt.
rot: Moderator wanne spricht, default: User wanne spricht.

Benutzeravatar
heinz
Beiträge: 535
Registriert: 20.12.2007 01:43:49

Re: Effizient mehrere Zeichen ausgeben

Beitrag von heinz » 11.05.2019 18:19:46

Hallo wanne
wanne hat geschrieben: ↑ zum Beitrag ↑
11.05.2019 14:18:01
Die Messungen sind grob unfair: Du misst immer nur den Zeitverbrauch der äußeren bash selbst.
Mein bestreben war auch nicht die exakte Zeit nur des Befehls zu messen, sondern eher verwertbare Vergleichswerte zu erhalten.
Wenn alle Befehle unter den gleichen Bedingungen gestartet werden (bash + Befehl) ist das doch auch gewaehrleistet. Oder sehe ich das falsch?
Time misst doch die Zeit, wie lange die bash gelaufen ist. Und die bash beendet sich erst wenn der Befehl durch ist.
wanne hat geschrieben: ↑ zum Beitrag ↑
11.05.2019 14:28:03
Das gilt für das neue Script im im Post vor mir nicht mehr.
Warum? Ich kann in dem Script in der Funktion zur Zeitmessung keine Aenderung finden. (Kann aber auch an mir liegen, war sehr spaet gestern... :) )
(Aber mir ist gerade aufgefallen, das ich in der Funktion "Zeit_messen" die globale Variable $befehl verwende anstatt $1...)
wanne hat geschrieben: ↑ zum Beitrag ↑
11.05.2019 14:18:01
Deswegen müssten die C-Varianten übelst abloosen, weil der gcc gar nicht schnell genug gestartet ist.
Aber genau darum geht es doch auch. Wie lange braucht ein Befehl um auf der Konsole eine Anzahl Zeichen zu schreiben.
Wenn ein Befehl z.B. awk nutzt muss halt auch erst awk gestartet werden. Das gehoert m.M.n. zur Laufzeit dazu.

wanne hat geschrieben: ↑ zum Beitrag ↑
11.05.2019 15:52:46
Hier ein etwas erweitertes Script: pastebin/?mode=view&s=40718
In Zeile 30

Code: Alles auswählen

groesse_fuer_groessentest=0
noch die 0 weglassen, damit man das Script auch ohne Angabe der Zeichenmenge laufen lassen kann...
* Anzahl der # kan ausgewählt werden
Hatte ich mir auch ueberlegt aber es dann gelassen, da ich das Script auch fuer andere Zeitmessungen benutzen moechte,
bei denen es nicht um eine Ausgabe von Zeichen geht.
Z.B. Schnellere Methoden zu finden mit sdl bestimmte Grafikeffekte zu erzeugen.
Aber fuer die Augabenstellung hier ist das eine sehr gute Idee...
* Hash statt Dateigröße wird verglichen
Stimmt, so kann man auch erkennen ob auch wirklich alle Zeichen die Richtigen sind.
* Deafault auf builtin time gesetzt
Das wundert mich etwas, laut "help time" kennt bash/time die Optionen -a, -o und -f garnicht? Zeigt aber keine Fehlermeldung und funktioniert normal?
* mktmp genutzt.
Es wird nicht korrekt aufgeraeumt wenn das Script nicht ganz durchlaeuft / vorzeitig beendet wird...
Liegt wohl an der Variablen "madedir". Wozu hast Du sie eigentlich eingefuegt?
Ich weiss, nach dem naechsten Boot ist /tmp wieder leer. Soll auch keine Kritik sein.

Schoenes Wochenende noch.
Gruss, heinz

wanne
Moderator
Beiträge: 7465
Registriert: 24.05.2010 12:39:42

Re: Effizient mehrere Zeichen ausgeben

Beitrag von wanne » 11.05.2019 18:49:00

Wenn alle Befehle unter den gleichen Bedingungen gestartet werden (bash + Befehl) ist das doch auch gewaehrleistet.
Ja. Aber die bash läuft halt schon.
Oder sehe ich das falsch? Time misst doch die Zeit, wie lange die bash gelaufen ist
Nein die Zeit in der der Befehl gelaufen ist. Da gehört weder das starten der bash noch das parsen des Befehls dazu. nicht dazu. In deinem Script startest du jedes mal eine neue bash. Dann ist wieder alles OK.
Wenn ein Befehl z.B. awk nutzt muss halt auch erst awk gestartet werden. Das gehoert m.M.n. zur Laufzeit dazu.
Ja. Aber es gibt halt einen falschen Eindruck. Die C-Varianten sind bei extrem vielen # deutlich schneller als die Konkurrenten mit yes. Eigentlich will man einen Grafen haben.
In Zeile 30
Gibt nochmal eine Unzulänglichkeit in meinem sed. Kommt nochmal ne Version.
Wozu hast Du sie eigentlich eingefuegt?
Wollte die Dateien direkt in /tmp liegen haben können. Werde den default aber wieder ändern.

benchmarke Gerade werde gleich mal Ergebnisse raus geben.
rot: Moderator wanne spricht, default: User wanne spricht.

Benutzeravatar
heinz
Beiträge: 535
Registriert: 20.12.2007 01:43:49

Re: Effizient mehrere Zeichen ausgeben

Beitrag von heinz » 11.05.2019 19:22:54

wanne hat geschrieben: ↑ zum Beitrag ↑
11.05.2019 18:49:00
Ja. Aber die bash läuft halt schon.
Ah, ok. Jetzt verstehe ich was Du meinst. (Glaub ich zumindest...)
Besser waere es also die Befehlsdatei ausfuehrbar zu machen und zu starten, anstatt sie mit /bin/bash zu starten.
Am liebsten waere mir auch gewesen den Befehlsstring, der ja schon in einer Variable steht, direkt auszufuehren ohne ihn in eine Datei zu schreiben.
Aber da in dem String die "wildesten" Zeichen vorkommen, hab ich es nicht anders hinbekommen.
wanne hat geschrieben: ↑ zum Beitrag ↑
11.05.2019 18:49:00
Nein die Zeit in der der Befehl gelaufen ist. Da gehört weder das starten der bash noch das parsen des Befehls dazu. nicht dazu.
Vielleicht reden wir aneinander vorbei. Ich meine, so wie es im Moment in meinem Script implementiert ist wir doch alles gemessen.
Der Start der bash, des Befehls, die Ausfuehrung des Befehle und das alles wieder zu beenden.
Anders kann ich es mir kaum vorstellen. (Kann aber auch an meiner Vorstellung liegen... ;) )
wanne hat geschrieben: ↑ zum Beitrag ↑
11.05.2019 18:49:00
Ja. Aber es gibt halt einen falschen Eindruck.
Da hast Du natuerlich recht. Aber wie schon geschrieben, war meine Absicht irgendwie alles abzudecken um das Script auch fuer andere Zwecke nuetzlich zu machen.
(Bin auch nicht so der Profi im Programmieren...)
wanne hat geschrieben: ↑ zum Beitrag ↑
11.05.2019 18:49:00
benchmarke Gerade werde gleich mal Ergebnisse raus geben.
Klasse, bin gespannt...


Hast Du uebrigens eine Erklaerung dafuer warum bash/time korrekt funktioniert obwohl es die Optionen garnicht kennen sollte?

Gruss, heinz

wanne
Moderator
Beiträge: 7465
Registriert: 24.05.2010 12:39:42

Re: Effizient mehrere Zeichen ausgeben

Beitrag von wanne » 12.05.2019 00:03:49

Vielleicht reden wir aneinander vorbei. Ich meine, so wie es im Moment in meinem Script implementiert ist wir doch alles gemessen.
Ja und ja.
In deinem Script ist das problem nicht mehr vorhanden. Nur bei den meisten Vorpostertn waren die bash-Befehle eben direkt hinter einem time und nicht eine extra bash geschrieben haben.

Hier meine Erlebnisse:
https://balja.org/pub/print.tar.xz
Hier die Ergebnisse:
https://balja.org/html/pics/printnum.svg
Leider wird das von Chrome und Firefox nicht angezeigt. Hab jetzt ne Stunde dran rumgespielt. Keine Ahnung, was da kaputt ist. Jeder andere Bildbetrachter hat kein Problem damit. Also einfach runter laden und ihr habt keine Probleme.
rot: Moderator wanne spricht, default: User wanne spricht.

wanne
Moderator
Beiträge: 7465
Registriert: 24.05.2010 12:39:42

Re: Effizient mehrere Zeichen ausgeben

Beitrag von wanne » 12.05.2019 03:51:12

Hier nochmal die von mir genutzten Befehle
pastebin/?mode=view&s=40719
Noch ein paar Anmerkungen:
  • Ich habe ein paar stellen Optimiert. Viele Befehle erzeugten falsche ausgaben. Neue Befehlsliste...
  • Man achte auf die doppelt logarithmischen Achsen
  • Ich habe immer irgend wann aufgehört, wenn die Laufzeiten zu lange wurden.
  • Die Python Variante explodiert irgend wann auf Laufzeiten im Minutenbereich, weil sie irgend wann swappen anfängt.
  • Für alle Varianten, wo die Ausgabe in 8 GiB passen ist die neue schnellste Variante eine in lua:

    Code: Alles auswählen

    echo "s=\"##########\";  for i=1,9 do; s=s .. s; end;  for i=1,math.floor(%numcharsHX/5120) do; io.write(s); end; for i=1,math.fmod(%numcharsHX,5120) do; io.write(\"#\"); end " | lua
    Die ist von mir stark optimiert. Aber auch ohne Optimierungen einfach mit einem loop der n mal die 10 # ausgibt ist die schneller als alles andere. (bzw. ähnlich wie die schnelleren perl Varianten) Der speed vom lua jit ist toll.
  • Es ist schon abzusehen: Aber die C Variante die im Moment auf Platz 2 ist, geht bei noch mehr Zeichen auf Platz 1.
    Da ist mein tmpfs aber zu klein. Hab dann Zeichen nach /dev/null schreiben lassen.
    Trotzdem: Die schnellste Variante für lange Ausgaben heißt

    Code: Alles auswählen

    echo -e "#include <string.h>\n#include <unistd.h>\n#include <sys/ioctl.h>\n int main(){ int bufflen=10240; char s[bufflen]; memset(s,'#',bufflen); int i=%numcharsHX/bufflen; while(i--) write(1,s,bufflen); i=%numcharsHX%bufflen; while(i--) write(1,s,1); }" | gcc -xc -; ./a.out
    Interessant dabei: selbst bei 8000000000 macht die Compiletilme noch deutlich was aus.O3 ist deutlich länger wie ohne, Vermutlich könnte man das nochmal durch das weglassend er Header optimieren. Ich will aber korrekten C-Code schreiben. Sinnvoll ist O3 nur bei der Variante mit putchar.
rot: Moderator wanne spricht, default: User wanne spricht.

Benutzeravatar
heinz
Beiträge: 535
Registriert: 20.12.2007 01:43:49

Re: Effizient mehrere Zeichen ausgeben

Beitrag von heinz » 12.05.2019 18:39:30

Wow, da ist ja eine richtig wissenschaftliche Untersuchung daraus geworden.
wanne hat geschrieben: ↑ zum Beitrag ↑
12.05.2019 00:03:49
Leider wird das von Chrome und Firefox nicht angezeigt.
Bei mir wird es korrekt angezeigt. (Firefox 66.0.5 (64-Bit))
Womit hast Du eigentlich die svg-Grafik erstellt? In der Datei "chart.eps" habe ich was von "PS-Adobe-3.0 EPSF-3.0" gelesen...

wanne
Moderator
Beiträge: 7465
Registriert: 24.05.2010 12:39:42

Re: Effizient mehrere Zeichen ausgeben

Beitrag von wanne » 12.05.2019 20:33:30

Womit hast Du eigentlich die svg-Grafik erstellt?
Inkscape. Habe auch ghostscript versucht. Produziert bei mir beides mal nur ein schwarzes Bild im Browser.
Die eps kommt einfach aus Libreoffice.
rot: Moderator wanne spricht, default: User wanne spricht.

Antworten