Ich habe die Geschwindigkeit von Bash und Python getestet, indem ich 1 Milliarde Mal eine Schleife ausgeführt habe.
$ cat python.py
#!/bin/python
# python v3.5
i=0;
while i<=1000000000:
i=i+1;
Bash-Code:
$ cat bash2.sh
#!/bin/bash
# bash v4.3
i=0
while [[ $i -le 1000000000 ]]
do
let i++
done
Mit dem time
Befehl habe ich herausgefunden, dass der Python-Code nur 48 Sekunden benötigt, während der Bash-Code über 1 Stunde dauerte, bevor ich das Skript beendet habe.
Warum ist das so? Ich erwartete, dass Bash schneller sein würde. Stimmt etwas mit meinem Skript nicht oder ist Bash mit diesem Skript wirklich viel langsamer?
echo echo hello >> $0
und führen Sie sie aus.Antworten:
Dies ist ein bekannter Fehler in der Bash. Siehe die Manpage und suche nach "BUGS":
;)
Für eine exzellente Einführung in die konzeptionellen Unterschiede zwischen Shell-Scripting und anderen Programmiersprachen empfehle ich dringend, Folgendes zu lesen:
Die zutreffendsten Auszüge:
Verwenden Sie in Shell-Skripten keine großen Schleifen.
quelle
Shell-Loops sind langsam und Bashs sind die langsamsten. Muscheln sind nicht dazu gedacht, schwere Arbeit in Schleifen zu verrichten. Shells sollen einige externe, optimierte Prozesse für Datenstapel starten.
Wie auch immer, ich war neugierig, wie sich Shell-Loops vergleichen lassen, also habe ich einen kleinen Benchmark gemacht:
( Details:
)
Die (abgekürzten) Ergebnisse (Zeit pro Iteration) sind:
Aus den Ergebnissen:
Wenn Sie eine etwas schnellere Shell-Schleife wünschen, dann befinden Sie sich
[[
in einer erweiterten Shell und haben auch die C-ähnliche for-Schleife , wenn Sie die Syntax und die schnelle Shell-Schleife wünschen. Verwenden Sie dann die C like for-Schleife. Sie können ungefähr 2-mal so schnell sein wiewhile [
-loops in derselben Shell.for (
Schleife bei etwa 2,7 us pro Iterationwhile [
Schleife mit ca. 5,8 µs pro IterationC für Schleifen kann 3-4 Dezimalstellen schneller sein. (Ich habe gehört, die Torvalds lieben C).
Die optimierte C for -Schleife ist 56500-mal schneller als die bash-
while [
Schleife (die langsamste Shell-Schleife) und 6750-mal schneller als die ksh-for (
Schleife (die schnellste Shell-Schleife).Auch hier sollte die Langsamkeit von Shells keine Rolle spielen, da das typische Muster bei Shells darin besteht, einige Prozesse von externen, optimierten Programmen auszulagern.
Mit diesem Muster machen es Shells oft einfacher, Skripte mit einer Leistung zu schreiben, die Python-Skripten überlegen ist.
Eine weitere zu berücksichtigende Sache ist die Startzeit.
dauert 30 bis 40 ms auf meinem PC, während Shells ca. 3 ms dauern. Wenn Sie viele Skripte starten, summiert sich dies schnell und Sie können sehr viel in den zusätzlichen 27-37 ms tun, die Python benötigt, um zu starten. Kleine Skripte können in diesem Zeitraum mehrmals abgearbeitet werden.
(NodeJs ist wahrscheinlich die schlechteste Skriptlaufzeit in dieser Abteilung, da der Start nur etwa 100 ms dauert (auch wenn es einmal gestartet ist, wird es Ihnen schwer fallen, unter den Skriptsprachen einen besseren Interpreten zu finden).
quelle
ksh88
, AT & Tksh93
,pdksh
,mksh
...) , denn es gibt eine ganze Menge von Variation zwischen ihnen. Fürbash
möchten Sie möglicherweise die Version angeben. Es hat in letzter Zeit einige Fortschritte gemacht (das gilt auch für andere Shells).from subprocess import *; p1=Popen(['echo', 'something'], stdout=PIPE); p2 = Popen(['grep', 'pattern'], stdin=p1.stdout, stdout=PIPE); Popen(['wc', '-c'], stdin=PIPE)
. Dies ist in der Tat umständlich, aber es sollte nicht schwierig sein, einepipeline
Funktion zu programmieren , die dies für eine beliebige Anzahl von Prozessen erledigt, was dazu führtpipeline(['echo', 'something'], ['grep', 'patter'], ['wc', '-c'])
.Ich habe ein paar Tests durchgeführt und auf meinem System Folgendes ausgeführt: Keiner hat die Größenordnung der Geschwindigkeit erreicht, die erforderlich wäre, um wettbewerbsfähig zu sein, aber Sie können es schneller machen:
Test 1: 18,233 s
test2: 20.45s
Test 3: 17,64 s
test4: 26,69s
test5: 12,79s
Der wichtige Teil in diesem letzten ist der Export LC_ALL = C. Ich habe festgestellt, dass viele Bash-Operationen erheblich schneller enden, wenn dies verwendet wird, insbesondere jede Regex-Funktion. Es zeigt auch eine undokumentierte Syntax für die Verwendung von {} und: als No-Op.
quelle
[[
viel schneller das ist als[
. Ich wusste nicht, dass LC_ALL = C (übrigens müssen Sie es nicht exportieren) einen Unterschied macht.[[
ist eine Bash eingebaut, und das[
ist wirklich/bin/[
dasselbe wie/bin/test
- ein externes Programm. Deshalb ist sie langsamer.[
ist in alle gängigen Shells integriert (trytype [
). Das externe Programm wird derzeit größtenteils nicht verwendet.Eine Shell ist effizient, wenn Sie sie für das verwenden, wofür sie entwickelt wurde (obwohl Effizienz selten das ist, wonach Sie in einer Shell suchen).
Eine Shell ist ein Befehlszeileninterpreter, mit dem Befehle ausgeführt und bei einer Aufgabe zusammengearbeitet werden können.
Wenn Sie auf eine Milliarde zählen möchten, rufen Sie einen (ein) Befehl zu zählen, wie
seq
,bc
,awk
oderpython
/perl
... Lauf 1000000000[[...]]
Befehle und 1000000000let
Befehle gebunden ist schrecklich ineffizient sein, vor allem mitbash
dem die langsamste Schale von allen ist.In dieser Hinsicht ist eine Shell viel schneller:
Natürlich wird der größte Teil der Arbeit von den Befehlen erledigt, die die Shell aufruft, wie es sein sollte.
Nun können Sie natürlich dasselbe tun mit
python
:Aber so würde man es nicht machen,
python
dapython
es sich in erster Linie um eine Programmiersprache und nicht um einen Befehlszeileninterpreter handelt.Beachten Sie, dass Sie Folgendes tun können:
Aber
python
würde tatsächlich eine Shell aufrufen, um diese Befehlszeile zu interpretieren!quelle
Antwort: Bash ist viel langsamer als Python.
Ein kleines Beispiel ist im Blog-Beitrag Leistung von mehreren Sprachen .
quelle
Nichts ist falsch (außer Ihren Erwartungen), da Python für nicht kompilierte Sprachen sehr schnell ist (siehe https://wiki.python.org/moin/PythonSpeed)
quelle
Neben den Kommentaren können Sie den Code ein wenig optimieren , z
Dieser Code sollte etwas kürzer sein.
Aber offensichtlich nicht schnell genug, um tatsächlich brauchbar zu sein.
quelle
Ich habe einen dramatischen Unterschied zwischen der Verwendung von logisch äquivalenten "while" - und "until" -Ausdrücken festgestellt:
Nicht, dass es wirklich eine enorme Relevanz für die Frage hat, ansonsten machen vielleicht manchmal kleine Unterschiede einen großen Unterschied, obwohl wir erwarten würden, dass sie gleichwertig sind.
quelle
((i==900000))
.=
für die Zuordnung. Es wird sofort true zurückgegeben. Es findet keine Schleife statt.