Performance, Programmierung

Der P-Code-Cache im Detail

Für die Verarbeitung von Prozeduren muss sich der ausführbare Prozedurcode im Hauptspeicher befinden. CONZEPT 16 lädt dabei nur den Code aus der Datenbank, der tatsächlich benötigt wird. Durch dieses Verfahren kann eine Prozedur unabhängig von den verfügbaren Speicherressourcen durchgeführt werden, um das Codemanagement braucht sich der Entwickler nicht zu kümmern. Für bestimmte Anwendungsfälle ist es dennoch hilfreich, die Mechanismen des P-Code-Caches zu kennen.


Generierung von Prozedurcode und Runtime-Daten

Der bei der Übersetzung einer Prozedur entstehende P-Code wird nicht in einem Stück gespeichert, sondern er besteht aus einer Anzahl von 2 KB großen Codeblöcken, die später unabhängig voneinander verwaltet werden können. Zur Ausführung der einzelnen Funktionen sind zusätzliche Metadaten erforderlich, deren Erzeugung ebenfalls bei der Prozedurübersetzung stattfindet, die aber getrennt vom Prozedurcode in der Datenbank abgelegt werden. Zu diesen Metadaten gehören beispielsweise die Namen, Argumenttypen und Startadressen der einzelnen Subfunktionen, Namen und Größen der globalen Datenbereiche sowie Variablen-Informationen für den Debugger.

Laden und Ausführen

Bevor die erste Anweisung einer Prozedur ausgeführt wird, müssen zunächst die Basis-Metadaten für die Subfunktionen geladen werden. Anhand des Namens der Subfunktion wird die Startadresse und somit der benötigte Codeblock der Prozedur ermittelt. Dieser Codeblock wird dann aus der Datenbank in den P-Code-Cache geladen, sofern er sich nicht bereits darin befindet. Anschließend startet die Abarbeitung des P-Codes. Bei jedem Programmsprung aus dem aktuellen Codeblock heraus wird anhand der Zieladresse der benötigte Codeblock ermittelt und dann geladen.

Cache-Management

Für die Codeblöcke aller Prozeduren gibt es einen gemeinsamen Pufferspeicher, dessen Größe unabhängig von der Gesamtmenge des in der Datenbank vorhandenen Prozedurcodes ist. Der Puffer füllt sich automatisch im Verlauf der Prozeduraufrufe. Ist der Puffer komplett gefüllt, wird beim Laden eines weiteren Codeblocks der bisher am längsten nicht verwendete Block aus dem Puffer entfernt. Falls die Puffergröße zu klein gewählt ist, müssen dieselben Codeblöcke innerhalb einer Verarbeitung mehrfach geladen werden, was naturgemäß die Verarbeitungsgeschwindigkeit bremst und den Netzwerk-Traffic erhöht. Die maximale Menge an gepufferten Metadaten ist ab Version 5.7.08 an die Puffergröße gekoppelt. In allen vorherigen Version gibt es eine statische Beschränkung.

Standardgrößen

Je nach Client-Typ ist die Standardgröße unterschiedlich definiert. Die Standardgröße ist davon abhängig, wie viele Instanzen des P-Code-Caches es typischerweise auf einem Rechner gibt und ob auch Prozeduren für die GUI zur Ausführung kommen. Ab Version 5.7.08 gibt es daher drei unterschiedliche Größenvorgaben (die API-DLL verwendet keine Standardgröße):

8 MB (GUI / wenige Instanzen)

– Standard Client
– Advanced Client
– 3.x Client
– Jobs in diesen Clients

2 MB (ohne GUI / viele Instanzen)

– SOA
– Jobs im SOA-Service
– PHP
– Druckprozessor
– Server

256 KB (ohne GUI / kein eigener Adressraum)

– ODBC
– Web-Schnittstelle

Änderung der Puffergröße

Mit zwei neuen Eigenschaften des _Sys-Objekts kann die aktuelle Größe des P-Code-Caches abgefragt und geändert werden (_Sys->spProcCacheLimitKB), außerdem lässt sich die aktuelle Pufferbelegung ermitteln (_Sys->spProcCacheKB). Im laufenden Betrieb kann sowohl eine Vergrößerung als auch eine Verkleinerung des Puffers erfolgen. Die Maximalgröße beträgt 64 MB, das Minimum liegt bei 256 KB.

mehr Puffer

Eine Vergrößerung des Puffers ist sinnvoll, wenn innerhalb einer Anwendungskomponente deutlich mehr Code geladen wird, als in den Standardpuffer hineinpasst. Zur Ermittlung dieser Menge wird beispielsweise die Applikation gestartet, der P-Code-Cache auf Maximalgröße _Sys->spProcCacheLimitKB # (1024 * 64) gestellt und die wichtigsten Funktionen einer Komponente ausgeführt. Abschließend wird die aktuelle Größe abgefragt. Für die nächste Anwendungskomponente muss der Client dann neu gestartet werden, da ansonsten der bisher geladene Prozedurcode natürlich im Puffer verbleibt. Anhand der ermittelten Werte kann dann entschieden werden, ob für die Applikation ein größerer Maximalwert sinnvoll ist. Dieser sollte dann innerhalb der Initialisierungsprozedur der Anwendung gesetzt werden. Alternativ ist das Limit beim SOA-Service auch in der Konfigurationsdatei des Tasks einstellbar.

weniger Puffer

Eine Verkleinerung des Puffers ist nur in den Fällen notwendig, in denen sehr viele Instanzen gleichzeitig laufen und wenig Speicher verfügbar ist, beispielsweise bei zahlreichen Datenbankbenutzern im SOA-Socket-Task oder vielen Jobs im Standard- oder Advanced-Client.

Keine Kommentare

Kommentar abgeben