Posted: Thu May 27, 2004 9:29 am
Ich habe mal Olafs letztes Beispiel als Referenz verwendet (damit die Testläufe nicht ganz so lange dauern) und mit meiner für große Tabellen optimierten Variante verglichen.
Neben dem Vergleich der Summen habe ich noch die jeweils besten Zeiten verglichen,
damit einzelne Ausreißer (s. z.B. die maximale Laufzeit bei 10 Einträgen, verglichen mit der Minimalen für 100) nicht das Ergebnis verfälschen:
Jetzt noch mal überarbeitet - ADD bei Ladenhuetern (und die damit obsoleten WHEN-OTHERS- bzw. ELSE-Anweisungen) weggelassen, und 1 Million Einträge geprüft.
Wie man sieht, bricht der Vorsprung meiner Version, der bei 100.000 Einträgen doch recht deutlich ist, bei einer Million Einträgen ganz schön ein.
Ob das mit einer Häufung der beim COLLECT auftretenden Hash-Kollisionen zusammenhängt?
Oder vielleicht eher mit dem READ ... BINARY SEARCH, das zunehmend ineffizienter wird.
Da könnte man noch etwas ändern - wenn auch mit negativem Einfluss auf kleinere itabs.
Mein Code (nach Einbau eines kleinen Hinweises von Stefan):
Neben dem Vergleich der Summen habe ich noch die jeweils besten Zeiten verglichen,
damit einzelne Ausreißer (s. z.B. die maximale Laufzeit bei 10 Einträgen, verglichen mit der Minimalen für 100) nicht das Ergebnis verfälschen:
Jetzt noch mal überarbeitet - ADD bei Ladenhuetern (und die damit obsoleten WHEN-OTHERS- bzw. ELSE-Anweisungen) weggelassen, und 1 Million Einträge geprüft.
- Code: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
- 27.05.2004
- --------------------------------------------------------------------------------
- Anz. Eintraege in Tabelle: 10 Maximale Materialnummer: 3
- Dauerbrenner: 0
- Saisonartikel: 0
- Ladenhueter: 3
- | Vergleich | Referenz
- Minimale Laufzeit: | 33 ms | 32 ms
- Maximale Laufzeit: | 76 ms | 172 ms
- Mittelwert Laufzeit: | 43 ms | 68 ms
- Vergleichsroutine ist um Faktor 1,03 langsamer als Referenzr
- Vergleichsroutine ist um Faktor 1,59 schneller (Summe)
- --------------------------------------------------------------------------------
- Anz. Eintraege in Tabelle: 100 Maximale Materialnummer: 7
- Dauerbrenner: 0
- Saisonartikel: 2
- Ladenhueter: 5
- | Vergleich | Referenz
- Minimale Laufzeit: | 136 ms | 132 ms
- Maximale Laufzeit: | 208 ms | 264 ms
- Mittelwert Laufzeit: | 151 ms | 160 ms
- Vergleichsroutine ist um Faktor 1,03 langsamer als Referenzr
- Vergleichsroutine ist um Faktor 1,06 schneller (Summe)
- --------------------------------------------------------------------------------
- Anz. Eintraege in Tabelle: 1.000 Maximale Materialnummer: 35
- Dauerbrenner: 10
- Saisonartikel: 22
- Ladenhueter: 3
- | Vergleich | Referenz
- Minimale Laufzeit: | 1.045 ms | 1.059 ms
- Maximale Laufzeit: | 1.105 ms | 1.442 ms
- Mittelwert Laufzeit: | 1.061 ms | 1.143 ms
- Vergleichsroutine ist um Faktor 1,01 schneller als Referenzr
- Vergleichsroutine ist um Faktor 1,08 schneller (Summe)
- --------------------------------------------------------------------------------
- Anz. Eintraege in Tabelle: 10.000 Maximale Materialnummer: 252
- Dauerbrenner: 161
- Saisonartikel: 90
- Ladenhueter: 1
- | Vergleich | Referenz
- Minimale Laufzeit: | 11.328 ms | 12.517 ms
- Maximale Laufzeit: | 15.673 ms | 13.763 ms
- Mittelwert Laufzeit: | 12.475 ms | 13.133 ms
- Vergleichsroutine ist um Faktor 1,10 schneller als Referenzr
- Vergleichsroutine ist um Faktor 1,05 schneller (Summe)
- --------------------------------------------------------------------------------
- Anz. Eintraege in Tabelle: 100.000 Maximale Materialnummer: 2.002
- Dauerbrenner: 1.646
- Saisonartikel: 355
- Ladenhueter: 1
- | Vergleich | Referenz
- Minimale Laufzeit: | 137.600 ms | 217.561 ms
- Maximale Laufzeit: | 146.181 ms | 268.567 ms
- Mittelwert Laufzeit: | 141.888 ms | 229.991 ms
- Vergleichsroutine ist um Faktor 1,58 schneller als Referenzr
- Vergleichsroutine ist um Faktor 1,62 schneller (Summe)
- --------------------------------------------------------------------------------
- Anz. Eintraege in Tabelle: 1.000.000 Maximale Materialnummer: 16.669
- Dauerbrenner: 15.319
- Saisonartikel: 1.348
- Ladenhueter: 2
- | Vergleich | Referenz
- Minimale Laufzeit: | 2.845.146 ms | 3.067.513 ms
- Maximale Laufzeit: | 2.898.925 ms | 3.122.678 ms
- Mittelwert Laufzeit: | 2.857.928 ms | 3.092.441 ms
- Vergleichsroutine ist um Faktor 1,08 schneller als Referenzr
- Vergleichsroutine ist um Faktor 1,08 schneller (Summe)
- --------------------------------------------------------------------------------
- Gesamtlaufzeit in Mikrosekunden: 68.170.039
- GeSHi ©
Wie man sieht, bricht der Vorsprung meiner Version, der bei 100.000 Einträgen doch recht deutlich ist, bei einer Million Einträgen ganz schön ein.
Ob das mit einer Häufung der beim COLLECT auftretenden Hash-Kollisionen zusammenhängt?
Oder vielleicht eher mit dem READ ... BINARY SEARCH, das zunehmend ineffizienter wird.
Da könnte man noch etwas ändern - wenn auch mit negativem Einfluss auf kleinere itabs.
Mein Code (nach Einbau eines kleinen Hinweises von Stefan):
- Code: [Select all] [Expand/Collapse] [Download] (Untitled.txt)
- p_max_matnr TYPE i
- * Uebergabe per Referenz ist schneller,
- * insbesondere das Kopieren der itab ist Aufwand
- *
- * und in dem Beispiel aendere ich die Parameter
- * auch nicht, dem Aufrufer kann es also egal sein,
- * dass ich die Werte nicht per VALUE uebergebe
- CHANGING p_ergebnis TYPE ty_ergebnis.
- *define _rt. " Test-Ausgabe Laufzeit von Einzelschritten
- * format color &1.
- * rt-from = rt-to.
- * get run time field rt-to.
- * rt-step = '&1'.
- * rt-diff = rt-to - rt-from.
- * write: / rt-tfill, rt-max, rt-step, rt-diff.
- *end-of-definition.
- *
- * statics: begin of rt, max type i, tfill type i, step, from type i, to type i, diff type i, end of rt.
- tabix_diff TYPE i,
- my_input TYPE ty_input.
- material TYPE ty_char_mat,
- * vom BUDAT des Originaltyps interessiert mich nur der Monat
- m(2) TYPE c,
- END OF ty_input2.
- tmp_input TYPE STANDARD TABLE OF ty_input2
- WITH NON-UNIQUE KEY material m.
- CLEAR p_ergebnis.
- * Da SORT in meinem ersten Beispiel am meisten Laufzeit verbrauchte,
- * jetzt ein Beispiel, das SORT nur auf eine kleinere Tabelle anwendet
- * COLLECT erfordert hier eine Typ-Konvertierung von MATERIAL
- *
- * Wenn es mehr als 2^22 Kombinationen Material und Monat gibt,
- * gibt es beim COLLECT allerdings einen Laufzeitfehler.
- * Gibt es mehr als 4 Millionen verschiedene Kombinationen?
- tmp_wa-material = my_input-material.
- tmp_wa-m = my_input-budat+4(2).
- * _rt 1.
- * Statt SORT Ein weiteres COLLECT in eine neue itab lohnt erst ab
- * 10^6 Eintraegen (bzw. mehr als 2002 verschiedenen Materialien)
- * _rt 2.
- * Suche den ersten Index fuer das naechstfolgende Material
- READ TABLE tmp_input " INTO tmp_wa
- WITH KEY material = tmp_mat
- BINARY SEARCH TRANSPORTING NO FIELDS.
- * Ermitteln der Anzahl Monate und passenden Zaehler erhoehen
- tabix_diff = sy-tabix - last_tabix.
- * je mehr Eintraege die itab hat, desto wahrscheinlicher sind
- * 12 Monate pro Material vorhanden, zumindest im derzeitigen
- * Testszenario (Anzahl verschiedener Materialien / Anzahl Eintraege
- *
- * Wenn ich die wahrscheinliche Haeufigkeit der Faelle kenne,
- * kann ich das auch in der Reihenfolge der WHEN-Anweisungen beruecksichtigen
- CASE tabix_diff.
- * ein ADD wegzulassen, war der Tipp von Stefan.
- * Er wollte aber die Anzahl Ladenhueter am Ende berechnen,
- * ich wollte diesen wahrscheinlichsten Fall weglassen und
- * so hoffentlich mehr sparen - hat aber nicht geklappt.
- * WHEN OTHERS.
- * ADD 1 TO p_ergebnis-ladenhueter.
- * WHEN 4.
- ** Materialnummern, die gar nicht vorkommen, werden auch in der Referenzloesung gezaehlt:
- *
- ** (Da verhaelt Olafs Loesung sich noch anders als die Referenz-Routine.
- ** Eine kleine Aenderung korrigiert das - und spart evtl. noch ein wenig Laufzeit.)
- * kein naechstes Material mehr, letzten Eintrag lesen
- READ TABLE tmp_input INTO tmp_wa
- INDEX sy-tfill TRANSPORTING material.
- WHEN p_max_matnr.
- tabix_diff = sy-tfill - last_tabix + 1.
- CASE tabix_diff.
- * WHEN OTHERS.
- * ADD 1 TO p_ergebnis-ladenhueter.
- * WHEN OTHERS.
- ** dieses Material und alle weiteren Materialien sind Ladenhueter
- * p_ergebnis-ladenhueter = p_ergebnis-ladenhueter - tmp_wa-material + p_max_matnr.
- EXIT.
- * zuletzt gelesenen Eintrag fuer naechsten Schleifendurchlauf merken
- last_tabix = sy-tabix.
- * p_ergebnis-dauerbrenner = p_max_matnr - p_ergebnis-ladenhueter - p_ergebnis-saison.
- p_ergebnis-ladenhueter = p_max_matnr - p_ergebnis-dauerbrenner - p_ergebnis-saison.
- * _rt 3.
- * format color off.
- GeSHi ©