PDA

View Full Version : RPG Programm durch Verwendung von DS für I/O Operationen



Seiten : [1] 2

Radinator
12-09-18, 15:27
Hallöchen!

Bin heut mehr so aus Zufall auf den Blog ibmsystemsmag.com gestoßen und habe mir folgenden Artikel durchgelesen: http://ibmsystemsmag.com/blogs/idevelop/archive/worth-a-second-2/

Darin wird behauptet, man kann seine Appliaktionen beschleuningen, indem man bei READ, CHAIN (also allen IO Operationen) im Ergebnisfeld eine DS angibt, die mit LIKEREC wie der Record, den man gelesen hat, definiert ist. Da sonst im Hintergrund die ganzen Felder per MOVE(L) und Z-ADD in den internen Buffer erst übertragen werden müssen.

Hatte das mal versucht nachzustellen:
Datei mit 4,6 Mio Datensätzen
- 30 Sek. Normallesezeit
- 30 Sek. Lesezeit mit DS in Resultfeld.
Ich habe zwar nur reines Lesen ohne schreiben (also die Datei mit IF E eingebunden), doch dachte ich mir, man könnte da eventuell einen Unterschied feststellen. Leider war das für mich nicht möglich.

Daher die Frage an Euch: Hat das jemand schon einmal ausprobiert und einen (messbaren) Unterschied produzieren können oder ist die Aussage (fast) nicht haltbar?

Lg Radinator

Fuerchau
12-09-18, 17:54
Das wird auch nichts bringen...weil:
Jede IO-Operation in RPG generiert entsprechende Moves von/in den Dateipuffer.
Die Anzahl der Moves hängt von 2 Faktoren ab:
a) die verwendeten Felder überhaupt
b) das verwenden einer DS incl. der Option "alle Felder"
Beim Update kann man sogar die Anzahl der Backmoves durch Angabe einer Feldliste einschränken.
Ob du nun ein Chain mit oder ohne DS angibst, der Aufwand ist immer derselbe.
Man kann halt nur einfach je Chain mehrere verschiedene Ziele angeben.

Teste mal den Unterschied (ohne DS) ob du nur 1 Feld bewegst nach dem Chain/Read oder 30.

Wenn du dich mit dem Thema Nano-Optimierungen beschäftigen willst, dann tu das.

Anders sieht es dann eher mit IO-Optimierungen aus, denn zumindest beim Lesen (Read nicht Chain) kann geblockt gelesen werden und folge Reads machen dann kein IO mehr bis der Block ausgelesen ist (ausschließlich I-Dateien).
Für O-Dateien (nur write) gilt dasselbe, hier wird ein Block vollgeschrieben bevor es einen IO gibt.
Mit dem Nachteil, dass beim Absturz u.U. ein ganzer Block an Daten verloren gehen kann (alles schon gehabt).
Bei Journalisierung wird für Write allerdings das Blocken wieder abgeschaltet, da jeder Write ja zur Transaktion gehörend im Journal stehen muss, da sonst ein Rollback nicht funktioniert.

Radinator
12-09-18, 19:03
Hallo @Fuerchau!
Danke für deine fixe Antwort!

Zu deiner Aussage "Ob du nun ein Chain mit oder ohne DS angibst, der Aufwand ist immer derselbe.":
Das verstehe ich nicht...so wie ich den Artikel verstanden habe erstellt der Compiler für jedes Feld aus dem Record eine Bewege-Operation. Im Unterschied zu der Verwendung von DS wird bei einer DS im Result-Feld nur eine einzige Bewege-Operation erstellt (Den ganzen Satz in die DS). Und genau das soll ja der Zeitvorteils sein.
Wenn ich jetzt einen Satz mit 20 oder 30 Feldern habe und in einem Fall für jedes Feld ein MOVE erstellt wird und im anderen nur ein einziger, kam mir die Erklärung bzw der Vorteil der DS doch sinnhaft vor. Nun sagt Du aber, dass das vom Aufwand her das gleiche wäre. Das verwirrt mich jetzt ein wenig.

Ging mir im Grunde nur darum eine Strukturauflösung eines Materialstamms in einem ERP zu beschleunigen. Normaldauer ohne Optimierung war ~ 15 Sekunden. Hatte gehofft das etwas schneller mit den DSen hinzubekommen. Hat leider nicht so funktioniert (habe dafür nur so um die 5 Felder bewegen müssen).
Zeit ließ sich dann mit SQL auf ~3 Sekunden reduzieren ;D

Lg Radinator

Pikachu
13-09-18, 08:43
Probier's doch mal mit einer abgespeckten logischen Datei, die nur die benötigten Felder hat.

Fuerchau
13-09-18, 09:03
Leider stimmt das nicht mit den "einzigen" Move beim Lesen in eine DS oder Schreiben/Update aus einer DS.
RPG ist schon immer feldorientiert gewesen.

SQL ist natürlich dann schneller, wenn eine komplexere Abfrage über einen SQL erledigt werden kann.
Dann entfällt nämlich die zusätzliche Übertragung zwischen Host-Variablen, SQL-generierten Variablen usw.

Natürlich kann SQL äußerst effektiv sein.
Ich habe letztlich eine rekursive CTE für eine Strukturauflösung über alles gemacht.
Das Ergebnis sind ca. 175.000 Zeilen in 5 Minuten. Laut SQL-Statistik wurden ca. 2,8Milliarden Zugriffe durchgeführt.

Radinator
13-09-18, 13:59
Also würde ich am Ende nur einen unterschied feststellen, wenn ich pro Lesezugriff mehrer 10 Felder (30+) bewege?

Fuerchau
13-09-18, 14:57
Im Nanosekundenbereich wohl ja.
Allerdings kann der %Timestamp nur Millisekunden und der SQL-Timestamp nur Microsekunden.
Da ist es schon schwierig in einer Multiuser-/Multijobumgebung zu messbaren Aussagen zu kommen.
Schließlich muss man ja auch wissen, was denn sonst so gerade läuft und ob man alleine auf dem System wirbelt.

Optimierungen gibt es häufiger im IO-Bereich durch vernünftige Verwendung von Indizes oder in der Array-Verarbeitung mit Lookup/%Lookup eher mit sortierten Arrays und Binär-Suchen zu arbeiten wenn es von der Aufgabe her möglich ist.
Gerade %lookup erlaubt ja die Angabe der max. zu verwendenden Einträge an Stelle aller Einträge zu durchforsten.
Es gibt da durchaus Potential Anwendungen zu entschlacken und damit zu beschleunigen und das liegt weniger daran ob man mal einen Move mehr oder weniger macht.

Radinator
14-09-18, 10:29
Deine Aussage bezüglich der %lookup Funktion entnehme ich, dass man solche Abfragen oder Programme auch beschleunigen kann, indem man z.B. bei meinem Fall zu einem Hauptartikel (bzw Material) alle Zutaten(Unter-Artikell, Arbeitsgänge, usw) nicht einzeln aus der Datenbank lesen und verarbeiten soll, sondern sich alle benötigten Sachen in Tabellen bzw Arrays laden soll und auf diese dann per %tlookup/%lookup zugreifen soll?

Hatte das bisher immer vermieden, da mein Kollege mir immer gesagt hat, ich soll die Daten möglich nur aus den Datenbanken und nicht "ins Programm laden".

Ich mein auf der AS400 auf der ich schreibe werden die PFs nur über LFs abgefragt, die dann eine Sortierung nach dem entsprechenden Kriterium haben (logisch *augenroll*).

Aber wenn ich die Zugriffszeit durch sortierte LFs nicht noch weiter senken kann und sich der Bereich, in dem ich eine Verbesserung durch Verwendung von Datenstrukturen im Resultfeld erzielen kann, sich nicht im Sekundenbereich befindet, dann glaube ich, dass die Version mit SQL doch am besten ist.

Pikachu
14-09-18, 11:41
Wenn ihr genügend Arbeitsspeicher habt, kann auch ein SETOBJACC auf die entsprechenden Dateien und Zugriffspfade einiges bringen.

Fuerchau
14-09-18, 18:29
SETOBJACC hat sich durch die intelligenteren Cachefunktionen längst überholt. Ausßerdem lohnt das nur, wenn man dafür eigene Speicherpools definert, die dem Paging dann nicht unterliegen.

Eas Arrays angeht, so habe ich nicht geagt, dass man alles und jedes cachen muss, da für einen Binärzugriff das Array auch jedesmal neu sortiert werden muss.
Dies lohnt eher für Arbeitsarrays, wenn diese sich sortieren lassen und eine Suche mit "=" erfolgt.
Für andere Suchen gibt es keine Binärsuche.
Allerdings ist dies bei Tabellen bis 100 Elementen auch nahezu unmessbar.

Wie bereits gesagt, SQL ist beim Suchen von Information und dem eingeschränkten Lesen (also nur gefilterte Ergebnisse) meist schneller als native Funktionen. Ins besonders wenn Index-Only-Access zum Tragen kommt. Nicht zu vergessen, VARLEN-Felder immer in ihrer Gesamtheit im Datensatz zu definieren da somit je Feld u.U. kein 2. IO erforderlich ist (Ausnahme LOB's, da gehts ja nicht anders).