Laufzeitoptimierung: Tuning-Challenge - Part I

Hinweise, Tips und Tricks, FAQs - keine Anfragen!!
18 Beiträge • Vorherige Seite 2 von 2 (current)
18 Beiträge Vorherige Seite 2 von 2 (current)

Beitrag von Frank Dittrich (Expert / 674 / 0 / 14 ) » 31.05.2004 11:03
Olaf P. hat geschrieben:Hallo zusammen,
da nun zu allen bisherigen Ergebnissen auch die Codings vorliegen, will ich Euch das Coding zu meiner zweiten Variante nicht vorenthalten.
Das duerfte wohl die für die meisten Fälle beste Lösung sein, noch dazu kompakter Code.
Was will man mehr.
Die Idee, die erste Hashed Table mit INSERT zu füllen und dann den SY-SUBRC auszuwerten, war genial.
(Und ab Release 6.40 kann die hashed table auch wesentlich mehr als 2^22 Einträge aufnehmen.
Zwar wird das COLLECT bzw. INSERT dann wegen zunehmehder Hash-Kollisionen immer langsamer, aber nicht so sehr, dass andere Alternativen wirklich besser sind.)

Allenfalls für Extremfälle kann man mit mehr Aufwand noch alternative Lösungen finden, die besser sind als Dein Besipiel.
Diese haben aber im Gegensatz zu Deinem Beispiel den Nachteil, dass (abgesehen von der schlechteren Wartbarkeit wegen des komplexeren Algorithmus) die Performance total in den Keller geht, wenn der Input gravierend von dem abweicht, wofür die Alternativ-Lösungen optimiert wurden.


Beitrag von black_adept (Top Expert / 3374 / 65 / 633 ) » 01.06.2004 00:19
Resumee:

Nach Auswertung der geposteten Routinen stelle ich fest, dass der beste Lösungsansatz wohl ein 2-Schritt-Verfahren zu sein scheint.

Im 1. Schritt wird die Tabelle auf eine sortierte und verdichtete Form gebracht ( pro Monat maximal 1 Einttrag ) und im 2. Schritt wird dann gezählt wieviele Einträge pro Material vorhanden sind.

Der pragmatische Ansatz wäre

Code: Alles auswählen.

  FIELD-SYMBOLS: <input> TYPE ty_input.
  DATA: zaehler TYPE i.
  CLEAR p_ergebnis.
* 1. Schritt - sortierte, verdichtete Tabelle

  SORT t_input by material budat.
  DELETE ADJACENT DUPLICATES FROM t_input COMPARING budat(6).

* 2. Schritt - zählen, wie oft jedes Material gebucht wurde
  LOOP AT t_input ASSIGNING <input>.

    AT NEW material.
      CLEAR zaehler.
    ENDAT.

    ADD 1 TO zaehler.

    AT END OF material.
      IF zaehler = 12.
        ADD 1 TO p_ergebnis-dauerbrenner.
      ELSEIF zaehler >= 10.
        ADD 1 TO p_ergebnis-saison.
      ENDIF.
    ENDAT.

  ENDLOOP.
  p_ergebnis-ladenhueter = p_max_matnr - p_ergebnis-dauerbrenner
                                       - p_ergebnis-saison.
Dies ist ein übersichtlicher und für spätere Entwickler leicht zu durchschauender Code und grob das, was ich wohl bei einem Kunden so stehen lassen würde.

Die weiteren Optimierungen beruhen darauf (wie Frank ja gepostet hatte), dass ein Großteil der Rechenzeit beim Sortieren der Tabelle draufgeht .
Eine überarbeitete Version hat Frank dann ja auch schon in seinem 1. (allgemeingültigem) Posting mitgeliefert, in dem der 1. Schritt nun so aussah.

Code: Alles auswählen.

 
* 1. Schritt überarbeitet
 LOOP AT t_input INTO my_input.
    tmp_wa-material = my_input-material.
    tmp_wa-m = my_input-budat+4(2).
    COLLECT tmp_wa INTO tmp_input.
  ENDLOOP.
Den finalen Schliff hat dann Olaf P. in seinem letzten Posting gegeben, in dem er die Hauptarbeit des Zählens in den 1. Schritt integriert hat mit dem Tool, das uns SAP zur Hand gibt - eine Tabelle und dem Befehl COLLECT. Die Methode den SY-SUBRC des Collect, den er für den 1. Schritt sowieso braucht, auszuwerten und in einer 2. Tabelle mitzählen zu lassen wie häufig pro Material der Collect wirklich einen neuen Eintrag erzeugt hat, führt zu einem effizienten und elegantem Code.

Abschließende Bemerkungen:
1.) Weitere Effizienzsteigerungen lassen sich dadurch erzielen, dass man Aussagen über die statistische Verteilung in der Tabelle INPUT machen kann und die Routinen dementsprechend anpasst.

2.) Wenn man nicht über "SORT, DELETE-ADJACENT-DUPLICATES" geht, sondern die verbesserte Version eine sortierte, verdichtete Tabelle zu erstellen verwendet, wird die Origaltabelle (INPUT) ja nicht verändert. Und da ein nicht unerheblicher Teil der Laufzeit für die Wertübergabe der Inputtabelle draufgeht, könnte man stattdessen eine Referenzübergabe verwenden (war aber nicht erlaubt lt. Aufgabenstellung - somit nur als Anmerkung)

3.) Ich habe die oben gepostete Demolösung mal mit der letzten Version von Olaf P. ( die schnellste gepostete) verglichen. Olafs Version ist bei 100.000 Einträgen ca. um den Faktor 2 schneller als die pragmatische Lösung.
Das sind Welten - aber verglichen mit der Ersparnis der Demolösung gegenüber der ursprünglichen Referenzlösung (Faktor > 100 ) nicht so viel.
Da kommts dann wohl auf das Projekt und die genauen Umgebungsparameter (Kunden) an, die bestimmen ob der pragmatische Ansatz schon ausreicht oder noch daran rumgefeilt werden muss. Möglich ist viel, wie man sieht...

4.) Danke an alle, die hier gepostet haben.

5.) Ich hänge noch eine überarbeitete Version des Programms an, welches die geposteten Lösungen enthält und es zulässt die einzelnen Versionen (bzw eigene) gegeneinander auszutesten. (Und statt des Mittelwert der Laufzeit alternativ die minimale Laufzeit bei mehreren Durchläufen als Faktor zur Berechnung zulassen kann. Hatte mich Frank drauf aufmerksam gemacht und beim Betrachten und Vergleichen der verschiedenen Lösungen bin ich auch zu der Ansicht gelangt, dass dies wohl der bessere Ansatz ist)
live long and prosper
Stefan Schmöcker

email: stefan@schmoecker.de

Beitrag von Olaf P. (ForumUser / 61 / 0 / 0 ) » 01.06.2004 07:01
Moin zusammen!

@Frank
Vielen Dank für das Kompliment. :)

@Stefan
M.E. fehlt beim "Delete Adjacent .. Comparing" noch die Materialnummer.

Es müsste auch noch ein bisschen schneller gehen, wenn man den "Clear zaehler" in die "End of Material"-Verarbeitung verschiebt und sich so die "At new"-Verarbeitung spart.

Bei meinen Tests hat sich auch gezeigt, dass der ASSIGNING langsamer als die Übertragung in eine Workarea ist. In der Praxis wird es schneller sein, da die Strukturen selten so schmal sind.

Ich finde es ist auch wichtig, dass Programme möglichst flexibel und robust sind. Konkret in Deinem Beispiel: Welche Routinen funktionieren noch, wenn die Materialnummern nicht numerisch oder fortlaufend sind?

@All
Hier ging es nur um die Performance und nichts anderes. In der Praxis würde ich eine übersichtlichere und wartbarere Routine einer schnelleren vorziehen, wenn die Differenz nur wenige Prozent beträgt. Ausnahme, das Programm läuft bspw. minütlich im Hintergrund und es kommt auf jede Sekunde an, die der Hintergrundprozess früher frei wird.

VG und eine schöne Woche
Olaf


Über diesen Beitrag


Unterstütze die Community und teile den Beitrag für mehr Leser und besseren Inhalt:

Aktuelle Forenbeiträge

Rechtsklick im ALV Tree
vor 19 Stunden von Ichse2 1 / 25

Vergleichbare Themen

[Linktip]Tuning des SAP BW & EasyBW
von M. Lahr » 25.03.2006 09:42
Laufzeitoptimierung
von ABAP_DEV » 27.07.2020 14:50
JCO Tutorial Part 1 - Direct JCO Connection
von Tim » 17.09.2004 14:15
Tabellen durchscannnen - Laufzeitoptimierung Z_SCAN_TABLE
von jspranz » 17.03.2006 14:39
Tabelle über Parameters laden Part II
von axxter » 11.08.2003 15:26