lullatsch
Anmeldungsdatum: 29. Juli 2014
Beiträge: 9
|
Hallo! Hat denn noch jemand Ratschläge wie ich mein unten angehängtes Skript optimieren könnte, so dass ich eine bessere Laufzeit erhalte? Ich muss dazu sagen, dass ich blutiger Anfänger bin und sicher nicht alles astrein ist, aber es erfüllt voll und ganz seinen Zweck, nur eben etwas langsam. Ich vermute mal durch die vielen Aufrufe der einzelnen Befehle. 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81 | #!/bin/bash
typeset -i COUNTER
typeset -i i
rm -f LZA_IMPORT_TEMP.csv
rm -f LZA_STRIP_WOTAG.csv
if [ -f LZA_IMPORT_SCHEMA.csv ]; then
rm -i LZA_IMPORT_SCHEMA.csv
echo "KURZNAME;A_TYP;DATUM;MEZ_MESZ;WERT;WOCHENTAG" > LZA_IMPORT_SCHEMA.csv
else
echo "KURZNAME;A_TYP;DATUM;MEZ_MESZ;WERT;WOCHENTAG" > LZA_IMPORT_SCHEMA.csv
fi
COUNTER=0
for ZEIT in {00..23}:{00,15,30,45}
do
array[$COUNTER]=$ZEIT
COUNTER=$COUNTER+1
done
echo ""
date -d '2 hours'
while true
do
echo ""
read -p "Geben Sie den gewünschten Wochentag (Mo, Di, Mi, Do, Fr, Sa, So) ein: " EINGABE
echo ""
case $EINGABE in
Mo) break ;;
Di) break ;;
Mi) break ;;
Do) break ;;
Fr) break ;;
Sa) break ;;
So) break ;;
*) echo ""
echo "Falsche Eingabe! Es ist nur eine der folgenden Abkürzungen Mo, Di, Mi, Do, Fr, Sa, So erlaubt."
esac
done
cat $1 | grep $EINGABE\" > LZA_STRIP_WOTAG.csv
ANZ_ZEILEN=$(cat LZA_STRIP_WOTAG.csv | wc -l)
for (( x=1 ; x<=$ANZ_ZEILEN ; x++ ))
do
rm -f LZA_IMPORT_TEMP.csv
echo "Zeile" $x "von" $ANZ_ZEILEN "wird verarbeitet..."
TYP=$(head -$x LZA_STRIP_WOTAG.csv | tail -1 | cut -d\, -f2 | sed 's/ //g' | sed 's/"//g')
WOTAG=$(head -$x LZA_STRIP_WOTAG.csv | tail -1 | cut -d\, -f1 | sed 's/ //g' | sed 's/"//g')
case $WOTAG in
Mo) WOTAG_LANG=Montag ;;
Di) WOTAG_LANG=Dienstag ;;
Mi) WOTAG_LANG=Mittwoch ;;
Do) WOTAG_LANG=Donnerstag ;;
Fr) WOTAG_LANG=Freitag ;;
Sa) WOTAG_LANG=Samstag ;;
So) WOTAG_LANG=Sonntag ;;
esac
i=0
for (( y=4 ; y<=194 ; y=y+2 ))
do
WERT=$(head -$x LZA_STRIP_WOTAG.csv | tail -1 | cut -d\, -f$y)
head -$x LZA_STRIP_WOTAG.csv | tail -1 | cut -d\, -f3 | tr \, ';' | sed 's/"/;'$TYP';31.01.2013 '${array[$i]}';[MEZ];'$WERT';'$WOTAG_LANG'/2' | sed -e 's/"//g' > LZA_IMPORT_TEMP.csv
cat LZA_IMPORT_TEMP.csv >> LZA_IMPORT_SCHEMA.csv
i=$i+1
done
done
rm -f LZA_IMPORT_TEMP.csv
rm -f LZA_STRIP_WOTAG.csv
echo ""
echo ""
echo -n "LZA erfolgreich eingelesen... --> "
date -d '2 hours'
|
|
MPW
Anmeldungsdatum: 4. Januar 2009
Beiträge: 3729
|
Hallo, also ein minimaler Fehler, der den Kohl sicher nicht fett macht: if [ -f LZA_IMPORT_SCHEMA.csv ]; then
rm -i LZA_IMPORT_SCHEMA.csv
echo "KURZNAME;A_TYP;DATUM;MEZ_MESZ;WERT;WOCHENTAG" > LZA_IMPORT_SCHEMA.csv
else
echo "KURZNAME;A_TYP;DATUM;MEZ_MESZ;WERT;WOCHENTAG" > LZA_IMPORT_SCHEMA.csv
fi Der Operator > löscht eine evtl. vorhandene Datei ohnehin. D.h. die ganze if-Abfrage kann weg. Genrell arbeitest du viel mit Strings. Bash ist da eben leider langsam. Grüße
MPW
|
lullatsch
(Themenstarter)
Anmeldungsdatum: 29. Juli 2014
Beiträge: 9
|
oh Danke ist mir gar nicht aufgefallen, aber das wird ja auch nur einmal aufgerufen. Von daher wird sich da nicht viel ändern. Womit kann ich denn strings besser bzw. schneller verarbeiten?
|
rennradler
Anmeldungsdatum: 27. Februar 2010
Beiträge: 1833
|
Ich sehe weniger das Problem in den Strigs sondern in solchen Zeilen:
head -$x LZA_STRIP_WOTAG.csv | tail -1 | cut -d\, -f3 | tr \, ';' | sed 's/"/;'$TYP';31.01.2013 '${array[$i]}';[MEZ];'$WERT';'$WOTAG_LANG'/2' | sed -e 's/"//g' > LZA_IMPORT_TEMP.csv
Hier werden bei jedem Durchlauf x Prozesse gestartet, um eine Datei zu manipulieren. Das ist arschlangsam. Für sowas wurde perl erfunden. Das bringt garantiert einen Faktor 100 in der Ausführungsgeswindigkeit.
|
u1000
Anmeldungsdatum: 2. Oktober 2011
Beiträge: 1850
|
Hi, ich sehe da viele tail cut head tail cut sed ... Da bist du vermutlich bei einem sauberen awk besser ausfgehoben. Viele grüße u1000
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
Das langsamste sind in der Tat die vielen Programmaufrufe, die Du da machst, UND dass Du für alles temporäre Dateien nimmst. Das ist überflüssig, dafür gibt es Variablen. Könntest Du mal bitte an einem Beispiel zeigen, was Du am Ende tatsächlich für Daten haben möchtest ? - ist die csv- Stuktur KURZNAME;A_TYP;DATUM;MEZ_MESZ;WERT;WOCHENTAG womöglich schon alles ? Das könnte man nämlich sehr einfach in ein Array einlesen: | old_IFS="$IFS"
IFS=";"
zeile="KURZNAME;A_TYP;DATUM;MEZ_MESZ;WERT;WOCHENTAG"
feld=($zeile)
echo "Wochentag: ${feld[5]}"
IFS="$old_IFS"
|
Und genauso kannst Du alle möglichen Zwischenwerte in anderen Variablen ablegen ... (n.b.: Deine eigenen Variablen solltest Du unbedingt $klein schreiben ! - $GROSS sind die Systemvariablen, und die möchtest Du nicht aus Versehen vermurksen. 😉 ) LG, track
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12801
|
lullatsch schrieb:
Hat denn noch jemand Ratschläge wie ich mein unten angehängtes Skript optimieren könnte, so dass ich eine bessere Laufzeit erhalte?
Es gibt auf jeden Fall zwei "Useless Use of cat Awards" für Zeile 42 und 44. ☺ Ich denke auch, das ganze ginge besser mit awk .
|
frostschutz
Anmeldungsdatum: 18. November 2010
Beiträge: 7651
|
Zeile 69 + 70 kannst du in einem Schritt machen, die temporäre Datei entfällt. sed a | sed b kann man fast immer als sed -e a -e b schreiben.
Ansonsten blicke ich nicht durch... XyProblem? PS: Die ganzen head tail Geschichten sind eine komische Art für ein read line, und auch hier wieder unnötige temporäre Dateien. Ich schätze das kostet dich hier am meisten zumal du die gleiche Zeile gleich zigfach auf diese Art und Weise holst...
|
user_unknown
Anmeldungsdatum: 10. August 2005
Beiträge: 17548
Wohnort: Berlin
|
lullatsch schrieb: Hallo! Hat denn noch jemand Ratschläge wie ich mein unten angehängtes Skript optimieren könnte, so dass ich eine bessere Laufzeit erhalte?
Wie schnell ist es denn, und wie schnell soll es werden?
|
lullatsch
(Themenstarter)
Anmeldungsdatum: 29. Juli 2014
Beiträge: 9
|
Danke erstmal für die zahlreichen Antworten. Ich denke auch, dass ich durch die Verknüpfung mehrerer Prozesse ziemlich viel Zeit verliere. | KURZNAME;A_TYP;DATUM;MEZ_MESZ;WERT;WOCHENTAG
|
Damit soll lediglich eine .csv angelegt werden mit diesem Kopf. An diese wird dann Zeile für Zeile mein Ergebnis drangehangen. Man muss jedoch dazu sagen, dass ich aktuell 9240 Zeilen (Messtellennamen) auslesen muss. Pro Messstelle werden dann zeilenweise Viertelstundenwerte (00:15 Uhr bis 23:45 Uhr) zugeordnet. Anschließend zweite Messstelle und wieder 96 Werte. Ich komme also in Summe auf über 800.000 Zeilen in meiner Ergebnisdatei. Momentan benötigt er pro Zeile knapp 6 Sekunden und in Summe dann um die 15 Stunden. Ich werd es wohl mal mit awk probieren müssen.
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
Generell sollte man sich den algorithmischen Ablauf klar machen und diesen ggf. optimieren. Wenn man Informatik studiert hat, sollte man dann eine O-Klasse bestimmt haben. Also etwa O(n * m) (Klingt jetzt bei Dir oberflächlich danach!). Wenn nicht, immerhin einen groben Ablaufplan, in dem man die Schleifen über Daten erkennen kann und wie oft diese durchlaufen werden (die Suche in Arrays o.ä. gehört auch dazu!). Je mehr Verschachtelung von verschiedenen Daten in Schleifen man hat, desto größer wird die O-Klasse und desto schlechte die Ausführungszeit tendenziell. Wenn man keinen besseren Ablauf findet, so kann man sich dann Gedanken machen, ob man das ganze im RAM erledigen kann, was sicherlich unheimlich viel schneller geht, als wenn man IO-Zugriffe zwischen drin hat. Da ich mich mit der Bash kaum mehr gut auskenne, kann ich aus Deinem Script auch nicht die Bohne ablesen, was es tut (will ich auch gar nicht 😀 ). Evtl. kannst Du uns ja die Ausgangslage mal textuell und ergänzend mit Demodaten beschreiben, so dass man mal gucken kann, wie man das ggf. in anderen Sprachen umsetzen könnte?
|
frostschutz
Anmeldungsdatum: 18. November 2010
Beiträge: 7651
|
Wirf doch erstmal das head tail raus, das ist wirklich das gruseligste in deinem Script, denke ich. Statt den temp. Dateien kannst du den Output direkt in eine Schleife pipen. while read line
do
something with "$line"
done < file Das ist dann viel effizienter als in einer Schleife tausendfach mit head -$x datei | tail -1 doch immer wieder ein und dieselbe Zeile rauszufischen.
|
track
Anmeldungsdatum: 26. Juni 2008
Beiträge: 7174
Wohnort: Wolfen (S-A)
|
lullatsch schrieb: | KURZNAME;A_TYP;DATUM;MEZ_MESZ;WERT;WOCHENTAG
|
Damit soll lediglich eine .csv angelegt werden mit diesem Kopf. An diese wird dann Zeile für Zeile mein Ergebnis drangehangen.
Wie sehe die Ergebniszeilen genau aus ? - Gib mal bitte ein Beispiel ! Man muss jedoch dazu sagen, dass ich aktuell 9240 Zeilen (Messtellennamen) auslesen muss. Pro Messstelle werden dann zeilenweise Viertelstundenwerte (00:15 Uhr bis 23:45 Uhr) zugeordnet. Anschließend zweite Messstelle und wieder 96 Werte. Ich komme also in Summe auf über 800.000 Zeilen in meiner Ergebnisdatei.
Das ist an sich überhaupt kein Problem ! - es kommt nur auf die Strategie an, dass diese ganzen Zeilen nicht 800.000 mal gelesen werden müssen ! (→ 1x reicht, den Rest kann man intern erledigen, egal ob mit Shell oder awk !) Momentan benötigt er pro Zeile knapp 6 Sekunden und in Summe dann um die 15 Stunden.
Logisch, wenn man 1 Mill. Zeilen 1 Mill. mal liest, ist das viel Holz ! ( 1 Bill. Zugriffe sozusagen ...) Ich werd es wohl mal mit awk probieren müssen.
Ist nicht unbedingt die Lösung, wie gesagt. Beschreib doch erstmal ganz normal in "Prosa", was Du genau machen willst. (und natürlich, wie eine Datenzeile genau aussieht: ein Beispiel-Datensatz zum testen, sozusagen.) LG, track p.s.: ich habe seinerzeit mit Shell / awk mal Datenbankdumps ausgewertet, mit 4 Mill. Datenzeilen. Da lagen typische Laufzeiten so um die 80 Sek., auf meinem 1 GHz-Athlon ... 😉
|
rklm
Projektleitung
Anmeldungsdatum: 16. Oktober 2011
Beiträge: 12801
|
Lysander schrieb: Generell sollte man sich den algorithmischen Ablauf klar machen und diesen ggf. optimieren. Wenn man Informatik studiert hat, sollte man dann eine O-Klasse bestimmt haben. Also etwa O(n * m) (Klingt jetzt bei Dir oberflächlich danach!).
Der Aufwand ist mindestens quadratisch in der Anzahl der Eingabezeilen (also o(n)), da für jede einzelne Zeile die Datei gelesen wird. Wenn man bedenkt, dass man das mit einem awk -Skript vermutlich in o(n) hinbekommt, ist das schon dramatisch.
Evtl. kannst Du uns ja die Ausgangslage mal textuell und ergänzend mit Demodaten beschreiben, so dass man mal gucken kann, wie man das ggf. in anderen Sprachen umsetzen könnte?
Ja, ein Beispiel für Eingabe und Ausgabe zusammen mit ein paar Erläuterungen hatte track ja auch schon angefragt. Damit kann man auf jeden Fall besser helfen.
|
Lysander
Anmeldungsdatum: 30. Juli 2008
Beiträge: 2669
Wohnort: Hamburg
|
rklm schrieb: Lysander schrieb:
Der Aufwand ist mindestens quadratisch in der Anzahl der Eingabezeilen (also o(n)), da für jede einzelne Zeile die Datei gelesen wird. Wenn man bedenkt, dass man das mit einem awk -Skript vermutlich in o(n) hinbekommt, ist das schon dramatisch.
Ich hatte das vor allem so verstanden, dass er jeder Zeile zusätzlich mit einer anderen aus einer anderen Datei kombiniert. Dass für jede Zeile die Datei gelesen wird, war mir nicht bewusst - wie gesagt interessiere ich mich seit Jahren nicht mehr für die Bash. Wenn das dann auch noch für die zweite Datei zutrifft, käme man ja sogar auf O(n^2 * m^2)!
|