45753
Goto Top

Batch beschleunigen - welchen code sollte man meiden

Hallo alle miteinander,

Da ich z.Z. mit Geschwindigkeitsproblemen kämpf brauchte ich mal Rat.

Meiner Ansicht nach sind die groessten Rechenkiller der Reihenfolge nach der attrib Befehl, die For-Schleife, und jeder zu viel gesetzter call bzw. goto Befehl - also damit auch jeder zu viel gesetzter Loop...

- wenn man z.B. anstatt des Loops in einer For-Schleife, in dem im unguenstigsten Fall der call Befehl 95 mal zum Einsatz kommt...

:regel_dr_loop
set "dr_max_suche=!fulldirx_dr:~%dr_zaehler_a%,1!"
if %dr_zaehler_a% EQU 97 ( set "dr_max_suche=96+"& goto :eof ) else ( if not "%dr_max_suche%" == "" set /a "dr_zaehler_a+=1"& goto :regel_dr_loop )
goto :eof

den Code ohne Loop untereinander schreibt,

if "%fulldirx_dr:~0,1%" == "" set "dr_max_suche=0"& goto :eof
if "%fulldirx_dr:~1,1%" == "" set "dr_max_suche=1"& goto :eof
if "%fulldirx_dr:~2,1%" == "" set "dr_max_suche=2"& goto :eof
...
...
...
if "%fulldirx_dr:~95,1%" == "" set "dr_max_suche=95"& goto :eof
if "%fulldirx_dr:~96,1%" == "" set "dr_max_suche=96"& goto :eof
set "dr_max_suche=96+"& goto :eof

dann ist der Rechenaufwand gleich um ein vielfaches geringer.

- Da meine Batch in der ich das so deutlich festgestellt habe mittlerweile ca. 800kb gross ist, frage ich mich gerade, ob der call bzw goto Sprung auch von der masse der Codes abhaengig ist ?!? Braucht die Batch dann laenger um das Sprungziel zu finden ?!?

- Wenn ich in einer For-Schleife einen call setze in dem ich dann wiederum ein For-Schleife habe, dann ist das genauso ein Killer.

- Wenn dann noch der attrib Befehl in diesem call der For-Schleife hinzukommt, dann kann man bei groesseren Operationen erst mal Kaffe trinken gehen.


Sind meine Erfahrungen korrekt ?

Auf was muss man noch achten um eine Batch nicht in die Knie zu zwingen ?


Gruesse, wobleibtdiezeit

[Edit]

Dieser Beitrag wurde bisher 85 mal aufgerufen.
Geschrieben von wobleibtdiezeit am 06.08.2007 um 16:54:15 Uhr.

Um die 85 (interessierten) Besucher und keiner weis was oder hat irgendwelche Erfahrungen darin gesammelt oder hat sich jemals so wie ich diese Frage gestellt ?

Nun ja, nicht was ich fuer eine lohnenswerte Diskussion halt muss auch gleich eine werden. Ein jemand der Wert auf schnellen Code legt ist in der Batch-Programmierung sowieso fehl am Platz.

Trotzdem waere es interessant zu wissen, welche Befehle in der Batch-Programmierung den Ablauf lahmen und welche nicht. z.B ist Attrib im vergleich zu Ren ein echter Klotz am Bein.

Im Web finde ich nur oberflächliche Infos.

Gruesse, wobleibtdiezeit

[Edit]

Content-Key: 65574

Url: https://administrator.de/contentid/65574

Printed on: April 25, 2024 at 19:04 o'clock

Member: TuXHunt3R
TuXHunt3R Aug 08, 2007 at 14:46:35 (UTC)
Goto Top
Da habe ich mir noch nicht gross Gedanken draüber gemacht.

Wenn wobleibtdiezeit sagt, dass sein batchfile 800 KB gross ist, weiss ich auch, wieso mich das nicht betrifft. Der grösste Batch, den ich je geschrieben habe, ist 200 KB gross!

Für komplexere Sachen verwende ich ohnehin Powershell-Scripts, diese sind schneller und weniger fehleranfällig
Mitglied: 45753
45753 Aug 08, 2007 at 16:44:47 (UTC)
Goto Top
Hallo TuXHunt3R,

wenigstens eine Antwort - THX!

Und danke für den Tipp.

Ich werde Powershell mal versuchen...

Gruesse,
wobleibtdiezeit
Member: TuXHunt3R
TuXHunt3R Aug 09, 2007 at 19:39:36 (UTC)
Goto Top
Tu das, das Ding macht richtig Spass!

Hier zu downloaden (Vista-Version):

http://www.microsoft.com/downloads/details.aspx?familyid=C6EF4735-C7DE- ...
Member: Ruebezahl
Ruebezahl Aug 10, 2007 at 17:27:17 (UTC)
Goto Top
Ein paar Betrachtungen zum Zeitverhalten von Batchdateien


Immer mal wieder wird die längere Laufzeit von Batchprogrammen bemängelt.
Dieser Mangel ist keine spezielle Eigenschaft, die nur Batchprogrammen zuzuschreiben wäre.
Es trifft alle Programiersysteme, die mit Interpretern arbeiten; mithin den neuzeitlichen Komandozeileninterpreter von Windows genauso wie auch das gute alte dBase: es sind alles Interpretersysteme.

Was ist das genau?

Wir werden in der Welt der Programmierung zwei grundsätzlich verschiedene Systeme antreffen:

(1) Die Compiler
Die übersetzen den von uns mühevoll erstellten Programmcode in seiner Gesamtheit in maschinenlesbaren Code und führen ihn dann aus.

(2) Die Interpreter
Interpreter übersetzen jede einzelne Programmzeile, die gerade zur Abarbeitung ansteht, in maschinenlesbaren Code und führen ihn dann aus.

Daraus ergeben sich für uns Batchprogrammierer einige Konsequenzen:
Dank der Zugehörigkeit des Kommandozeileninterpreters zu Punkt (2) wird jede Programmzeile übersetzt und ausgeführt, wenn sie zur Abarbeitung ansteht. Warum schreibe ich das hier ein zweites Mal? Es ist gut, sich öfter mal daran zu erinnern! Im Eifer der Programmierung vergisst man hin und wieder manches, so auch die Konsequenzen davon.
(a) Hier nur nebenbei: Syntaxfehler werden natürlich auch erst dann gefunden, wenn der Interpreter diese Zeile abarbeitet. Bei komplizierten Strukturen und / oder Bedingungen wird das oft übersehen.
(b) Der Kommandozeileninterpreter übersetzt jede Zeile JEDES MAL, wenn er auf sie trifft. Wenn eine Schleife also x-mal durchlaufen wird, dann wird JEDE EINZELNE ZEILE x-mal übersetzt und x-mal ausgeführt.
Das ist vom Zeitverhalten unter Umständen fatal, denn die Arbeitsleistung ergibt sich dann aus
Zeilenzahl der Schleife x 2 x Anzahl der Durchläufe
Da hat unser Interpreter ganz schön zu tun!

Kein Wunder also, das ein einfaches Auflisten einzelner Zeilen statt einer eleganten Schleife hier die Lösung zu sein scheint!

Ist es wirklich die Lösung? Nicht ganz, denn wenn wir zur Compiler-Konkurrenz schielen, werden wir Schleifen finden, die an Komplexität mitunter kaum zu übertreffen sind.
Genau in diesen Augenblick kommt einer aus dem Batch-Lager und bietet uns eine Spaghetti-Lösung an?!? Kann der denn überhaupt programmieren? Leider ist es so, das einige Schleifenfetischisten Programmcode nur nach der Komplexität beurteilen und nicht ob sich jemand aus dem Batch-Lager Gedanken über das Zeitverhalten gemacht hat.
Hier wird es wohl keine allgemeingültige Lösung geben. Es ist an uns, mit dem uns eigenen Fingerspitzengefühl genau die Variante zu wählen, die dem Zweck genügt: Wenn der liebe Chef mit schnellen Ergebnissen zufrieden gestellt werden muss, wird es wohl die weniger stilvolle Auflistung einzelner Programmzeilen sein. Kollegen von der Compiler-Zunft werden wir dagegen die andere Version zeigen, die elegantere, die so viel komplizierten Code enthält, das auch die sich sicher sein können, das man im Batch-Lager programmieren kann.

Außerdem gibt es da noch ein Aspekt, der leider allzu oft übersehen wird: ist es nicht schön, wenn unser Batchprogramm etwas länger läuft? Dann haben wir Gelegenheit, mit der hier im Forum schon mal erwähnten rothaarigen Praktikanten Kaffee zu trinken.

Herzliche Grüße
an alle

Ruebezahl
Member: Biber
Biber Aug 10, 2007 at 23:13:33 (UTC)
Goto Top
Moin wobleibtdiezeit,

dann muss ich wohl - als bekennender Batcher - auch ein paar Worte loswerden zu dem Thema.

Nachdem Ruebezahl schon den Weg bereitet hat mit der (durchaus notwendigen) Kontextbetrachtung möchte ich einige seiner Gedanken mal konsequent zu Ende denken.

  • ein Interpreter ist naturgemäß stinkelangsam
  • ein Interpreter hat ebenso naturbedingt wenige "programmiersprachliche" Strukturen wie Schleifen, Verzweigungen, intern separierbare/selbstdefinierbare Unterprozeduren oder User Defined Functions
  • ein Interpreter schleppt in jeder einzelnen gatesverdammten Anweisung das komplette globale Environment des Interpreters (z.B. der CMD.exe) mit sich herum
Insbesondere der letzte Punkt kann "teuer" werden.

Eine ganz simple Anweisung wie eine For/F -Anweisung, die einen (internen!) Befehl wie DIR ausführt, führt ja nicht diesen internen Befehl aus.
Sondern: Ein "FOR /F %i in ('dir /b *.txt') do ..." führt ja dazu, dass für den "inneren" DIR-Aufruf eine neue Instanz der CMD.exe aufgerufen wird.
Quasi ein "Cmd.exe /c dir *.txt" wird ausgeführt.
Für diese CMD.exe-Instanz wird auch wieder das komplette Environment aufgebaut (auch wenn nur ein interner DIR-Befehl ausgeführt werden soll).

D.h. alle Umgebungsvariable (siehe SET) werden generieriert, alle hinterlegbaren Start-/AutoRun-etc-Routinen geladen usw.
Die Schlauberger, die ihre CMD.exe ganz doll individuell starten mit ein paar automatisch beim CMD-Interpreter geladenen Doskey-Makros, einem Setzen der Farben/Fenstergröße, dem Wechseln ins Verzeichnis c:\Batches und einem CLS.. die sind gekniffen. -->siehe Parameter /D der CMD.exe.

Ebenso bestraft werden alle Batchler durch viele, viele Windows-Programme, die dreisterweise ihren eigenen Programmpfad an den Anfang der Umgebungsvariable PATH setzen.
Was ich damit meine könnt ihr nachvollziehen, wenn ihr mal am CMD-Prompt "PATH" (ohne Anführungszeichen) eintippt.
Meist haben sich dort Programme verewigt, von denen ihr gar nicht wisst, dass die irgendwelche commandline-Features haben.
Insbesondere Datenbanken und Kompiler sind da masslos.

Wenn nun, um auf wobleibtdiezeits Beispiel einzugehen, ein externer Befehl (eine beliebige *.bat, *.exe, *.com oder was immer in der Variablen %PATHEXT% steht) aufgerufen wird... also ATTR oder irgendetwas ohne explizite Pfadangabe...
...dann wird unter Umständen erst mal in einem Verzeichnis "c:\Oracle\Oracle 11.0\Bin" und "D:\CyberCpp\bin" nach dieser Datei gesucht. Weil die im Suchpfad ganz vorne stehen.
Bei Batches, die 200 KB groß sind, da ummiert sich diese Verzögerung schon...

Grundsätzlich sollte die Bätcherei weniger als "Programmierung" aufgefasst werden - der Anspruch, irgendetwas vollständig in native Batch lösen zu wollen hat eher etwas Rührendes als etwas Ehrenwertes. Und mehr als Kittmasse, mit der sich einzelne Spezialbefehle sinnvoll und automatisiert verketten lassen.

Immer auf eins der zahllosen One-Trick-Utilities zurückgreifen, die auf eine simple Aufgabe spezialisiert sind. Einleuchtendes Beispiel hierfür:
Eine Textdatei zeilenweise mit einer FOR /F -Anweisung durchzuwackeln und jede einzelne Zeile auf einen bestimmten String zu prüfen ist 1000x langsamer als die relevanten Zeilen vorher mit Find.exe oder FindStr.exe oder ähnlichem zu filtern.

Aber im Grunde meines Herzen sind eigentlich in der Tat diese blutjungen rothaarigen Praktikantinnen das Hauptargument fürs Rumbätscheln..face-wink

Grüße
Biber
Mitglied: 45753
45753 Aug 11, 2007 at 11:33:49 (UTC)
Goto Top
Tach Ruebezahl und Biber,

Danke fuer Eure ausfuehrlichen Informationen. Damit kann man was anfangen...
Leider sind in Euren Infos auch viele meiner Befuerchtungen eingetreten...
Das ist wie es ist zu lesen hilft einem aber weiter und man muss nicht mehr im Dunkeln tappen.

Gruesse, wobleibtdiezeit
Member: Biber
Biber Aug 11, 2007 at 12:41:05 (UTC)
Goto Top
Moin wobleibtdiezeit,

ein Nachtrag noch, bzw. einen Sachverhalt, der Dir auch bewusst sein sollte bei 200KB-Batchdateien...

Wenn in einer Batchdatei Sprungmarken enthalten sind ("goto :Machdas" oder "call :TuJenes"),
dann "weiß" der CMD-Interpreter anders als ein Compiler nicht vorher, wo er hinspringen muss.

Bei jedem "GOTO :X" wird wieder die gesamte Batchdatei gelesen von Zeile 1 bis zur Zeile mit der Marke ":X".

So etwas musst du auch berücksichtigen wenn Du in Zeile 15000 folgende so ein Konstrukt hast
...
15000 if "%var%"=="A" goto :A_Fall
15001 if "%var%"=="B" goto :B_Fall
15002 goto :InJedemFall
15003 :InJedemFall
...
15555 :A_Fall
15556 .....bla
15557 goto :inJedemFall
....

In diesem Beispiel musst Du Dir klarmachen, dass z.B der optisch kleine Sprung von Zeile 15002 nach Zeile 15003 bedeutet, dass erstmal wieder 15000 Zeilen nach der Marke ":InJedemFall" abgescannt werden müssen.

Gruss
Biber
Member: Pireli
Pireli Sep 14, 2008 at 21:32:47 (UTC)
Goto Top
Ich würde das Script nicht von einem Netzlaufwerk sondern es auf den lokalen Client kopieren und dann ausführen. Dann geht es um einiges schneller bei so einer großen batch...

Gruß