Zum Artikel
< >

Aktives GUI-Element

Statisches GUI-Element

Quelltext

WPS-Objekt

Datei/Pfad

Befehlszeile

Inhalt Eingabefeld

[Tastenkombination]

mehr

Mit Theseus die Speichernutzung in OS/2 untersuchen
Teil 1

von Sjoerd Visser, © Februar 2007

Die meisten OS/2-Benutzer haben wohl bereits unter Speicherproblemen gelitten, auch wenn Sie sich dessen gar nicht bewußt waren. Wenn man die dabei involvierten Mechanismen ein wenig kennt, kann das reichhaltige Hilfsprogramm Theseus von IBM dabei helfen, mögliche Übeltäter und Lösungen zu finden.

Speicher erschöpft mit 1 GB verfügbaren RAM

Eine häufige Klage bei OS/2-Anwendern lautet: Ich habe 2 GB RAM, aber kann sie nicht vollständig nutzen: Wenn ich große Programme starte, erhalte ich die Fehlermeldung nicht genügend freier Speicher, obwohl ich noch 1 GB freien RAM habe.

Ich habe einige Tricks herausgefunden, mit denen sich die Nutzung der Systemspeicherbereiche erhöhen läßt (großer JFS-Cache, 1 GB Speicher für XP in VPC), aber es war mir unmöglich, 1 GB realen RAM für Benutzerprogramme bereitzustellen. Großen Programmen habe ich Zugriff auf hohe Speicherbereiche gegeben, so daß ein Mangel an virtuellem Speicher nicht das Problem sein sollte.

Ich habe viel experimentiert. Die grundsätzliche Methode dabei war, so viele Anwendungen wie möglich unter Verwendung verschiedener CONFIG.SYS-Einstellungen zu laden. Um die Zustände vergleichbar zu machen, habe ich einen Ordner mit Referenzen häufig benötigter Dateien, Ordner und Programmobjekte verwendet. Ich habe einen separaten Ordner verwendet, da das Hinzufügen der Anwendungen in den Ordner Systemstart oder zur STARTUP.CMD ein instabiles OS/2-System zur Folge hätte haben können.

Ich habe die Anwendungen daher von Hand gestartet, eine Befehlszeile aufgerufen und mit Theseus eine Speicher-Momentaufnahme angefertigt.

Stapeldatei zur Erzeugung einer Speicher-Momentaufnahme
rem Theseus_Memory_Snapshot.cmd
cd cd Theseus
getram.exe 1 0 file c:\theseus.txt
type c:\config.sys >> c:\theseus.txt
call getlinmp.cmd >> c:\theseus.txt
start fte c:\theseus.txt
exit

Zu meiner Überraschung fand ich heraus, daß die Verwendung von THREADS=1024 oder höher einen negativen Einfluß auf die Anzahl der Programme, die ich starten konnte, hatte. Als das System begann instabil zu werden, lag die Zahl der tatsächlich benötigten THREADS bei weniger als 350. Ich reduzierte den Eintrag daher auf 400.

Ähnliche Erfahrungen machte ich mit hohen Werten für VIRTUALDRESSLIMIT (VAL) in der CONFIG.SYS: Ein VAL von 2048 oder höher kann für bestimmte Server von Nutzen sein, doch 1024 bis 1536 sind für einen WPS-Benutzer besser. Damit war das System länger stabil. Odin-isierte Programme benötigen nicht das Windows-VAL von 2048 – es wird nur von MS-Office benötigt, doch ich verwende OpenOffice

Die überraschendste Erkenntnis war, daß ich für Benutzerprogramme höchstens 500-700 MB RAM zur Verfügung hatte. Mehr Programme zu laden oder den Speicherbedarf anwachsen zu lassen, machte das System instabil. Außer, es handelte sich um Java-Programme, da diese vorrangig privaten Speicher benutzen.

Ziel meiner Ladetests war es zu beurteilen, ob OS/2 sein Versprechen bezüglich virtuellem Speicher halten konnte. Nun, es konnte es nicht, denn Theseus fand dabei immer einen Mangel an nutzbarem virtuellen Speicher in der gemeinsamen Speicherregion.

Aber wer oder was ist Theseus? Welche Art von Speicher fehlte den Anwendungen? Und wie mißt man virtuellen Speicher in der gemeinsamen Region? Das findet man heraus, indem man Theseus verwendet.

Theseus

Der Theseus der griechischen Mythologie war laut Sage ein König des alten Athen und übrigens auch derjenige, der den Minotaurus im Labyrinth von Kreta tötete. Die ganze Geschichte können Sie auch in der Wiki Enzyklopädie nachlesen.

Der Theseus aus der Feder von IBM-Ingenieuren allerdings findet seinen Weg eher durch das Labyrinth von der Speichernutzung unter OS/2. Und bevor Sie sich mit ihm einlassen, sollten Sie Ihre Hausaufgaben gemacht haben – andernfalls werden Sie schnell in den Untiefen zwischen realem und virtuellem Speicher untergehen.

Theseus ist IBMs OS/2-Speicheranalyseprogramm. Verschiedene Versionen davon kursieren auf dem Hobbes-Spiegelserver der OS/2 Site Australia. Wählen Sie dort einfach die Version, die zu Ihrem OS/2-System paßt. In älteren OS/2-Versionen braucht Theseus unter Umständen noch einen Gerätetreiber, um auf die OS/2-Interna zugreifen zu können.

Theseus' Prozeßhierarchie

Theseus Prozeßhierarchie
Abb. 1: Theseus' Prozeßhierarchie

Zu Programmbeginn wird die Theseus' Prozeßhierarchie angezeigt.

Darin wird der OS/2-Prozeßbaum angezeigt, beginnend mit sysinit, das die Einträge in CONFIG.SYS liest und ausführt, bis zu den Kindprozessen, die von der protected mode shell (protshell, diesem Fall PMShell) gestartet wurden.

Ein Doppelklick auf einen der Prozesse ermittelt dessen allgemeine Prozeßinformationen (General Process Information): PTDA, Threads, Exit-Liste, offene Dateien, Umgebung, sowie Programm und dessen Parameter.

Wenn Sie den Eintrag eines Prozesses aus der Liste in Theseus Prozeßhierarchie markieren, können Sie außerdem weitere spezifische Prozeßinformationen dafür einsehen mittels des Menüeintrags Process: Hier finden Sie Details zu Arbeitsbedarf (Working set), Speichernutzung, Speicherleckermittlung, Allgemeine Prozeßinformationen, PTDA, LDT, Seitentabelle, Zusammenfassung für private Objekte, Zusammenfassung für gemeinsame Objekte, private Regionentabelle ("Arena Table") und gemeinsame Regionentabelle (s. auch Abb.).

Theseus liefert womöglich mehr Informationen über das OS/2-Speicherlabyrinth, als man überhaupt wissen mag. Wenn man allerdings die Dynamik von OS/2 verstehen möchte, dann führt kein Weg an Theseus und dessen exzellenten Hilfsdateien (Help > Explanation of the contents of this window) vorbei.

Ich werde einige nützliche Optionen erläutern.

Bestimmung des Arbeitsbedarfs

Der Arbeitsbedarf ("working set of a program", Delta) ist die Menge an Adreßraum, die ein Programm in einem bestimmten Zeitraum verwendet. Da virtueller Speicher dem Prozessor als physischer Speicher präsentiert werden muß, werden in einem gleichen Zeitraum Programme mit einem kleinem Arbeitsbedarf schneller ausgeführt als Programme, die auf große Mengen an virtuellem Speicher (EXE-Code, DLLs, Daten) zugreifen.

Idealerweise sollte der Arbeitsbedarf eines Programms in den Prozessor-Cache passen. Ebenso sollte der Arbeitsbedarf des ganzen Systems (Kernel + aktive Anwendungen) in den RAM passen, denn: Die grundlegende Idee hinter dem Prinzip des präemptiven Multitasking ist, daß der Prozessor nur dann optimal genutzt werden kann, wenn es einen permanenten Hintergrundprozeß (bzw. -Task oder -Thread) gibt, der die freie Prozessorzeit nutzt, während andere Threads auf Ein-/Ausgabeoperationen warten ("Taste drücken um fortzusetzen..."). Der Arbeitsbedarf eines jeden dieser wartenden Threads (unmittelbar benötigter Code und Daten) muß sich jedoch natürlich ebenfalls im RAM befinden.

Im schlimmsten Fall ist der Arbeitsbedarfs aller laufenden Anwendungen größer als der Hauptspeicher. In diesem Fall nämlich muß OS/2 – sobald einem Prozeß wieder Prozessorzeit zugeteilt wird – Speicherbereiche auf die Festplatte auslagern und die anderen benötigten von dort zurückholen. Das führt dann zum sogenannten disk thrashing (Plattenüberlastung): Das System ist mehr damit beschäftigt, Speicher auszulagern als Programme auszuführen.

Theseus kann sowohl den Arbeitsbedarf für einen einzelnen Prozeß als auch für das ganze System messen. Mit Theseus können Sie selbst die tatsächliche Speichernutzung in bestimmten Situationen ermitteln.

Um den Arbeitsbedarf eines Prozesses zu bestimmen, wählen Sie zunächst den Prozeß in der Theseus Prozeßhierarchie aus, dann Process > Working Set aus dem Menü und starten die Messung mittels Functions > Working Set Start.

Dann arbeiten Sie ein wenig mit dem jeweiligen Programm (ich habe beispielsweise diesen Text hier in OpenOffice 1.1.5 geladen und ein wenig getippt). Stoppen Sie danach die Messung über den Menüpunkt Functions > Working Set Stop.

Die Ausgabe (Output > Save as) sieht wie folgt aus:

Working Set for the Process with PID = 009C, name = 'SOFFICE':
Use the 'Functions' pull-down or the 'Popup Menu'
  to start and stop the data collection.
Collection started: interval = 5, Working Set is 12 intervals.
current time ------ Process -------   ------ System DLL -----
hh:mm:ss.tt     now      ws   acc'd       now      ws   acc'd
22:59:25.52   8.199M  8.199M  8.199M    4.422M  4.422M  4.422M
22:59:30.40   3.508M  8.969M  8.969M    3.172M  4.605M  4.605M
22:59:35.40   2.613M  9.004M  9.004M    2.531M  4.633M  4.633M
22:59:40.39   2.289M  9.008M  9.008M    2.156M  4.633M  4.633M
22:59:45.40   2.621M  9.035M  9.035M    2.961M  4.680M  4.680M
5 samples collected.
                                 Process      DLL    Total
Absolute minimum amount of memory: 8.199M   4.422M  12.621M
Recommended amount of memory:      9.035M   4.680M  13.715M
Total amount of accessed memory:   9.035M   4.680M  13.715M

Im vorliegenden Beispiel brauche ich also 13,7 MB (Recommended amount of memory) des RAMs, um meinen Theseus-Artikel im OpenOffice-Writer zu laden und ein wenig zu bearbeiten. Wäre nur die absolute Mindestanforderung (Absolute minimum amount of memory) von 12,6 MB verfügbar gewesen, wäre es also schon zu Speicherauslagerungen gekommen.

Gemäß den Auswertungen unter Speichernutzung (wo die Verwendung des niedrigen virtuellen Speichers gemessen wird) betrug die Menge an niedrigem virtuellen Speicher, der für SOFFICE alloziert wurde, 161 MB, wovon 30 MB zugesichert wurden. Auf einem speicherarmen System wäre damit mindestens die Hälfte des zugesicherten Speichers in der SWAPPER.DAT gelandet und 131 MB des allozierten virtuellen Speichers wären nie verwendet worden – zumindest nicht im vorliegenden Fall.

Der AE editor hatte einen kleineren Arbeitsbedarf (5 MB), der auf 2 MB zurückging, nachdem das Dokument geladen wurde. Aber kleinere Programme haben nicht unbedingt auch immer einen kleineren Arbeitsbedarf als große. Java Server, die große Mengen an virtuellem Speicher allozieren, können durchaus einen sehr kleinen Arbeitsbedarf haben, wenn ihre Kernfunktionen auf kluge Art und Weise abgewickelt werden.

Die Workplace Shell (PMShell) mit Ihrem Funktionsreichtum hat einen relativ kleinen Arbeitsbedarf (1 bis 2 MB werden angesprochen) im Vergleich zu Ihrem Potential, solange man nicht in kurzer Zeit alle Ordner öffnet oder checkini laufen läßt. Checkini greift in sehr kurzer Zeit auf viele WPS DLLs zu:

current time ------ Process -------   ------ System DLL -----
hh:mm:ss.tt     now      ws   acc'd       now      ws   acc'd
23:39:21.34   2.840M 22.414M 26.184M    3.211M  7.813M 16.051M
23:39:26.34   3.262M 22.277M 26.660M    2.539M  7.844M 16.117M
23:39:31.33   1.852M 13.773M 26.664M    2.145M  7.188M 16.117M
The selected process has terminated.
Periodic update stopped.
23 samples collected.
                                 Process      DLL    Total
Absolute minimum amount of memory:11.730M   8.012M  14.953M
Recommended amount of memory:     22.719M  12.219M  31.898M
Total amount of accessed memory:  26.664M  16.117M  42.781M

Diese WPS lief auf einem eCS-System mit 128 MB RAM. Laut Theseus > Process > Memory Usage wurden 71 MB alloziert und 24 MB zugesichert. Doch nur 10 MB befanden sich im RAM. Während checkini /C lief, wuchs der allozierte Speicher auf 87 MB, wovon 35 MB zugesichert und 15 im RAM waren. Die SWAPPER.DAT wurde nicht verwendet, demnach wurden also 20 MB des zugesicherten Speichers anderen Speichernutzern entzogen. Gemeinsamer Speicher des XWP Daemon und die erste PMShell (PM) könnten hierfür in Frage kommen. Es kann aber auch andere Erklärungen dafür geben, da der hohe Speicher nicht in die Messungen der Speichernutzung einbezogen wird.

Wie dem auch sei, Fakt ist, daß der Arbeitsbedarf großer Prozesse kleingehalten werden kann, solange man nicht alle Leistungsmerkmale innerhalb kurzer Zeit verwendet. Aus diesem Grund ist die exzessive Nutzung virtuellen Speichers an sich kein Problem. OS/2 wird dadurch nicht langsamer, da der Großteil des allozierten Speichers so gut wie niemals zugesichert wird. Und nur ein kleiner Teil des zugesicherten virtuellen Speichers muß sich im RAM befinden. Das ist der Arbeitsbedarf. Der Rest des zugesicherten Speichers kann ausgelagert werden.

Die Seitenauslagerungs-Algorithmen versuchen grundsätzlich, den Arbeitsbedarf der aktiven Programme im Speicher zu halten. Und solange der Arbeitsbedarf des gesamten Systems (Theseus > System > Working Set) in den Hauptspeicher paßt, laufen alle aktiven Programme stabil, wie sich ihr Laufzustand nicht ändert.

Wenn Sie ein weiteres Programm starten oder ein Vordergrund-Programm sich ändert, erhöht sich der Arbeitsbedarf dieses jeweiligen Programms – auf Kosten der anderen Programme. Im Prinzip kann jede Aktion (schon ein einzelner Mausklick) eine Umschichtung in der Zuordnung der virtuellen Speicherbereiche zu den zugehörigen Prozessen mit sich bringen, bevor das ganze Speichergebilde wieder in einen stabilen Zustand wechselt. Auf Systemen mit geringem Hauptspeicher lassen sich diese Änderungen am Arbeitsbedarf anhand einer aktiven SWAPPER.DAT leichter beobachten als auf modernen Rechnern mit Unmengen von RAM. Diese nämlich leiden lediglich unter Problemen bei der Allozierung virtuellen Speichers.

Speichernutzung

Theseus > Process > Memory Utilization veranschaulicht, welche Arten von Speicherresourcen ein OS/2-Programm benutzt. Der Schwerpunkt liegt hierbei auf der »klassischen« OS/2 2 v4.x-Nutzung des virtuellen Speichers. Das ist allerdings kein Nachteil, da die wirklich gravierenden Ladeprobleme in der niedrigen virtuellen Speicherregion (virtueller Adreßraum < 512 MB) auftauchen, wo sich alle 16- und die meisten 32-Bit-Programme und -DLLs tummeln.

Unter Misc > Content update wählen Sie den Eintrag Start Periodic Update. Legen Sie dann das Aktualisierungsintervall mittels Misc > Content Update > Options fest. Wenn Sie zwei Fenster für die Speichernutzung öffnen und nur in einem die zyklische Aktualisierung starten, können Sie sehr schön sehen, wie mit der Zeit ein Zuwachs oder eine Reduzierung der Speichernutzung der Prozesse vonstatten geht. Aber was genau kann man da sehen und was bedeutet es?

Um einen Überblick zu gewinnen, schauen wir uns zunächst die Zeilen mit der Beschreibung am oberen Rand sowie die Zeilen mit der Zusammenfassung an. Wie sieht es denn mit der Speichernutzung von Seamonkey aus?

Speichernutzung von Seamonkey
Abb. 2: Speichernutzung von Seamonkey

Bytes allocated ist die Menge an niedrigem virtuellen Speicher, die von der virtuellen Speicherverwaltung dem Programm nach dessen Anforderung angeboten wurde.

Für Seamonkey wurden 88,298 MB aus den ersten 512 MB des Adreßraums alloziert. Wäre Seamonkey nicht nur kurz zu Testzwecken gelaufen, hätten Sie hier mit einem massiven Zuwachs rechnen können (> 200 MB).

Die allozierten virtuellen Speicheradressen, auf die während der Programmausführung zugegriffen wurde, mußten in den physischen Speicher geladen werden. Daher erhielten sie einen Eintrag in der Seitentabelle (Page Table) welche die Zuordnung von virtuellen Speicheradressen zu physischen Speicheradressen verwaltet. Das schlägt sich im Wert Memory committed (zugesicherter Speicher) = 41.005 MB nieder. Da das Programm diese virtuellen Adressen auch erneut ansprechen kann, muß die Seitentabelle diese Adressen weiter im Auge behalten, bis das Programm die virtuellen Adressen wieder freigibt oder ganz beendet wird.

Ein Teil des kürzlich zugesicherten Speichers befindet sich noch im RAM (Bytes present = 9.712 MB). Das müßte der Arbeitsbedarf des Programms sein. Aber die am wenigsten verwendeten Bereiche des zugesicherten Speichers (in 4 KB-Blöcken) konnten ausgelagert werden (Bytes swapped = 14.516 MiB), um anderen Prozessen freien physischen Speicher bereitzustellen. Einige kleinere Speicherobjekte konnten in komprimierter Form in der Systemspeicherregion gehalten werden (in der »speicherinternen Auslagerung«): Das Auslagern von einigen wenigen, nicht akut benötigten Bytes ist nicht effizient, wenn dafür entweder ein ganzer 4 KB-Block geopfert oder die SWAPPER.DAT bemüht werden muß. Mehr dazu auch unter Swapper.

Der dezimale Wert Number present steht für die Anzahl der Speicherobjekte, die das Programm im RAM verwendet. Der hexadezimale Wert Bytes each gibt die dafür benötigte Speichermege an. Der häufig auftretende Wert 0x1000 Bytes entspricht übrigens dem einer Speicherseite (4096 Bytes, also 4 KB). Unter Description ist angegeben, wo sich dieser Speicherbereich befindet (um welchen Speichertyp es sich handelt).

Zur Gewinnung einer schnellen Übersicht darüber, wie das Programm die niedrigen privaten und gemeinsamen Speicherregionen (im RAM) nutzt, genügt also ein Blick auf den dezimalen Wert bei number present.

Auf die grün eingefärbten hexadezimalen Werte können Sie übrigens klicken – dann erscheint ein Popup-Fenster mit detaillierten Beschreibungen der privaten und gemeinsamen allozierten virtuellen Speicherobjekte und deren absoluten Größenangaben in MB. In dieser Detailansicht wiederum können Sie auf die hexadezimalen Adressen klicken, wodurch ein weiteres Popup-Fenster erscheint und einen Blick auf 100 Bytes des tatsächlichen Speicherinhalts gestattet. Meist ist nur ein Bruchteil des allozierten virtuellen Speichers im RAM präsent.

Beachten Sie, daß lineare Adressen oberhalb von 1FFF FFFF in der Speichernutzung nicht angezeigt werden. Wenn Sie mehr über die Nutzung der hohen Speicherregion wissen möchten, verwenden Sie dafür die Menüeinträge Process > Private and Shared Object Summaries oder System > Linear usage by process.

Speichernutzung der Workplace Shell bestimmen

Schauen wir uns jetzt die WPS eines eCS 1.2-Systems mit 128 MB RAM an, nachdem genügend Aktionen getätigt und ausreichend Programme gestartet wurden, um die SWAPPER.DAT mit dem »gemächlich-schreibenden« (lazy-writing) MEMMAN=SWAP,PROTECT auf eine Größe von ungefähr 30 MB wachsen zu lassen.

Memory Utilization for Process with PID = 002A, name = 'PMSHELL':
    bytes      bytes    number  bytes      bytes    bytes
allocated  committed   present   each    present  swapped  description
 00000760   00000760         1   0760   00000760 00000000  PTDA
 000090B4   000090B4        49   02F4   000090B4 00000000  TCBs
 00031000   00030000        42   1000   0002A000 00006000  TSDs
 00010000   00009000         9   1000   00009000 00000000  LDT
 000001E0   000001E0       480   01E0   000001E0 00000000  Process Page Directory
 00078000   0002C000        44   1000   0002C000 00000000  Page Tables
 07310000   02C89000      3712   1000   00E80000 0042C000  Accessible Shared memory
 03270000   014DD000      1679   1000   0068F000 002EC000  Originated Shared memory
 023A0000   00B4A000       759   1000   002F7000 001E5000  Private memory
 000C29F4   0006E9F4                    000689F4 00006000  Total System
 03270000   014DD000                    0068F000 002EC000  Total Shared originated
 023A0000   00B4A000                    002F7000 001E5000  Total Private
 --------   --------                    -------- --------
 056D29F4   020959F4                    009EE9F4 004D7000  Total RAM/SWAPPER for this Process
    88906      33366                       10170     4956  (in Kbytes)
   86.823     32.585                       9.933    4.840  (in Mbytes)

Die letzte Zeile zeigt, daß 86,823 MB des virtuellen Speichers für die WPS alloziert und 32,585 MB davon tatsächlich angesprochen wurden (sozusagen »gemächlich zugesichert«). Von diesem zugesicherten Speicher befanden sich noch 9,933 MB im RAM und 4,840 MB wurden bereits ausgelagert. Der restliche zugesicherte Speicher wurde somit entweder bereits wieder freigegeben oder er befand sich in der komprimierten SWAPPER.DAT im System-RAM. Dies kann ich leider nicht genau bestimmen.

Nur zum Vergleich: Für den unbenutzten PM Spooler wurden 29 MB alloziert, er benötigte lediglich 141 KB des RAM und 592 KB wurden ausgelagert. Sein Arbeitsbedarf war somit minimal, aber er konnte immer noch einen Druckjob annehmen.

Das Abbild eines Prozesses im virtuellen Speicher

Wie Sie bereits sehen konnten, setzt sich der virtuelle Speicher eines Prozesses aus verschiedenen Komponenten zusammen: System-, privater und gemeinsamer Speicher.

Die ersten Einträge betreffen den System-RAM: Die Per Task Data Area (PTDA, taskbezogene Datenregion), Thread Control Block (TCB, Thread-Kontrollblock), Thread Swappable Data (TSD, auslagerungsfähige Daten eines threads), Local Descriptor Table (LDT, lokale Deskriptortabelle), Process Page Directory (Verzeichnis der Prozeß-Speicherseite) und die Page Tables (Speicherseitentabellen). Sie alle laufen unter der Bezeichnung RAM, da sie statisch sind: Vorzugsweise im RAM, obwohl einige Tabellen ausgelagert werden können. Sie werden vom Prozessor und dem Betriebssystem für elementare Aufgaben benötigt, wie beispielsweise das Umschalten zwischen Tasks.

Die EXE-Datei ist Bestandteil des privaten Speichers eines Programms, also dem Teil des virtuellen Speichers, den das Programm nicht mit anderen teilen mag. Wenn Sie auf die grüne hexadezimale Adresse klicken, können Sie die DLLs einsehen, die darin verwendet werden. Sie werden sehen, daß viele gemeinsam verwendete DLLs auch privat verwendet (gelinkt) werden können.

Der Wert für originated shared memory ("bereitgestellter gemeinsamer Speicher") ist der Beitrag des Programms zur gemeinsam genutzten Speicherregion. (Wenn Sie Hex nicht mögen, klicken Sie einfach auf die grüne Hex-Adresse.) Es hat mich überrascht, daß viele DLLs nicht aus dem jeweiligen Programmverzeichnis stammen. Innerhalb einer grafischen Benutzeroberfläche wie Windows oder OS/2, die von vielen Prozessen geteilt wird, können die Grenzen zwischen Prozessen wirklich verschwimmen…

Aber natürlich sind DLLs dafür geschaffen, gemeinsam benutzt zu werden. Daher ist der Wert accessible shared memory hier der relevante: Der absolute Bereich an gemeinsam genutztem Speicher, der vom Prozeß angesprochen werden kann. Darin sind eingeschlossen: Der vom Prozeß originär bereitgestellte gemeinsame Speicher (originated shared memory), die vom Prozeß benutzten DLLs, der verwendete Teil des von anderen Prozessen bereitgestellten gemeinsamen Speichers und der zusätzlich (mit DosGetSharedMem) erworbene gemeinsame Speicher.

Wenn man allerdings einmal den Wert originated shared memory mit dem unter accessible shared memory eines ausgelösten Prozesses wie CNTRL.EXE vergleicht, stellt man mit Erstaunen fest, daß die beiden nur selten voneinander abweichen. Tatsächlich teilt sich CTRL Speicher mit allen möglichen DLLs, die gar nichts mit dessen Funktionalität zu tun haben: DIVE, INNOWIN, OOWIN, PSCRIPT und FLASHWIN, um nur ein paar zu nennen. Da CNTRL.EXE weder Flash-Multimediainhalte wiedergibt noch grafische Druckausgaben erzeugt, werden diese Speicherbereiche also niemals zugesichert.

Diese DLLs könnten allen Anwendungen angeboten worden sein, da die OS/2-Entwickler nicht vorhersehen konnten, welches Programm sie vielleicht einmal benutzen würde. Doch das unnötige Linken von DLLs könnte in Zusammenhang stehen mit den Fehlermeldungen bezüglich unzureichendem (virtuellen) Speicher, die bei OS/2-Anwendern nun des öfteren auftauchen.

Wenn Sie beabsichtigen, einen OS/2-Server ausschließlich im Textmodus zu betreiben, sollten Sie überlegen, CMD.EXE sowohl bei SET RUNWORKPLACE= als auch für die protected mode shell (PROTSHELL=) anzugeben. Viele DLLs, die Sie für die eigentliche Kernaufgabe nicht benutzen, werden dadurch gar nicht erst geladen.

Funktionen

Beispiel für disassemblierten physischen Speicherinhalt von Mozilla Abb. 3: Beispiel für disassemblierten physischen Speicherinhalt von Mozilla

Die Hypertextfunktionen von Theseus erlauben es, immer tiefer und tiefer in einen bestimmten Prozeß hinein zu schauen. Selbst das Disassemblieren von Code ist damit möglich.

Wenn Sie eine grüne Speicheradresse sehen, können Sie deren Funktionen abfragen. Wählen Sie die Adresse aus und dann eine Funktion.

Als Anzeigeoptionen stehen zur Verfügung:

Unter Misc > Double click options können Sie bestimmen, in welchem Format die ersten 100 Bytes dargestellt werden: In Bytes, Wort-Format, Doppelwort-Format oder sogar disassembliert.

In der nebenstehenden Abbildung sehen Sie, was Mozilla gerade an der physischen Adresse 3E0C A000 (bei ca. 993 MiB) in disassembliertem Code treibt.

Umrechung hexadezimaler Adresse zu dezimal mittels der Zwischenablage

Wenn Sie eine hexadezimale Adresse – beispielsweise 3E0C A000 – in eine dezimale Adresse umrechnen wollen, können Sie dafür den Windows-Calculator oder den eCS-Rechner benutzen. Diese müssen sich dafür jeweils im wissenschaftlichen Modus befinden.

Kopieren Sie einfach die hexadezimale Notation von Theseus in die Zwischenablage mittels Mark > Find > Copy selection to clipboard und fügen Sie sie in den verwendeten Rechner ein, während sich dieser im wissenschaftlichen Modus befindet. Als Auswahl stehen Ihnen Hex, Oct, Dec und Bin zur Verfügung. Nachdem Sie die hex-Adresse 3E0C A000 in den Rechner eingefügt haben, stellen Sie den Rechnermodus auf Dezimal um. Nun erhalten Sie die dezimale Byteadresse (1.041.014.784).

Um für eine Größe in Bytes-Angabe die entsprechenden Kilobytes zu erhalten (von OS/2 als Synonym von 1024 Byte betrachtet, in SI-Terminologie allerdings 1.000 Byte entsprechend) teilen Sie den Wert durch 1024. Diesen Wert teilen Sie nochmals durch 1024, um das zu erhalten, was OS/2 als Megabytes betrachtet (1024 Kilobytes – laut SI-Notation allerdings 1.000.000 Bytes).

Zu den unterschiedlichen Berechnungsarten dieser Einheiten gibt es übrigens auch einen Passus in Wikipedia.

Wo wir gerade davon sprechen – das Verwenden der Zwischenablage ist ein typischer Fall zur Nutzung gemeinsamen Speichers. Da 16-Bit-Anwendungen auch die Zwischenablage nutzen können, sind alle Inhalte der Zwischenablage immer in der gemeinsamen Region eines Prozesses.

"Odin"isierte Programme wie Acrobat 4 und OpenOffice haben Schwierigkeiten bei der gemeinsamen Nutzung von Zwischenablageinhalten in den nahezu erschöpften niedrigen gemeinsamen Regionen – wobei sie selbst meistens für die Erschöpfung verantwortlich sind. Man kann dann Prozesse namens SOFFICE.EXE (ClipboardWindow) oder AROS2.EXE (transport Window) in Watchcat finden, wenn das jeweilige Programm hängt.

Speicherseitentabelle

Seitentabelle für Nutzung des virtuellen Speichers durch Java
Abb. 4: Seitentabelle für Nutzung des virtuellen Speichers durch Java

Über Process > Page Table gelangen Sie zur Virtual Page Table (Virtuelle Speicherseitentabelle) des Prozesses. Die virtuelle Speicherseitentabelle setzt eine lineare Adresse im virtuellen Speicher in eine physische Adresse des RAM um. Programme, die den hohen Speicher benutzen, besitzen hex-Einträge, die bei der linearen Adresse 2000 0000 (512 MB) oder höher liegen. Die linearen Adressen von Programmen, die sich in der niedrigen Speicherregion tummeln, beginnen statt dessen bei 0 oder 1 und reichen nicht höher als 1FFF FFFF.

Blättern Sie ruhig einmal herunter bis hex 2000 0000 um das zu prüfen. Ein grober Anhaltspunkt zum Verhältnis zwischen der Nutzung von hohem und niedrigem Speicher ist die Position des Griffpunktes auf der Bildlaufleiste an der rechten Seite des Theseus-Fensters. Im nebenstehenden Beispiel (Java) lag fast die Hälfte der benutzten virtuellen Speicheradressen oberhalb von 512 MB.

Lokale Deskriptortabelle (Local Descriptor Table, LDT)

Der Intel-286-Prozessor verwendete spezielle Tabellen, um den virtuellen Speicher eines jeden Prozesses zu verfolgen. Jeder Prozeß im abgesicherten Modus hatte eine eindeutige Lokale Deskriptortabelle (LDT) und das System als Ganzes eine Globale Deskriptortabelle (GDT). Die GDT enthielt ebenfalls Einträge für gemeinsame Speicherbereiche. GDT- und LDT-Einträge, die auf dieselbe Speicheradresse zeigten, nannte man Aliase.

Die LDT eines Programms enthielt essentielle Informationen zu dessen Nutzung von virtuellem Speicher: Adressen (segmentiert!), ob der virtuelle Speicherbereich beschreibbar ist, sich im Speicher befindet etc. Mehr darüber erfahren Sie, wenn Sie eine der Tabellen aufrufen und dann die Theseus-Kontexthilfe dazu bemühen.

32-Bit-OS/2-Programme verwenden das flache, lineare 0:32 Addressierungsschema des Intel-368-Prozessors. Allerdings erwarten 16-Bit-Programme des abgesicherten Modus nach wie vor 16-Bit-Adressen in einer LDT zu finden. Daher verwendete das 32-Bit OS/2 2.0 die Technik des »32-Bit zu 16-Bit Umbruchs« (thunking), um sicherzustellen, daß eine lineare 0:32-Adresse des Intel 386 eine entsprechende 16:16 Selektor/Offset-Entsprechung in der LDT und GDT besaß (LDT-Stückelung). Die begrenzte Kapazität der LDT spielte auch ein Rolle bei der Limitierung von OS/2s virtuellem Adreßraum auf 512 MB (8191*64 KB). Aus diesem Grund werden auch nur die virtuellen Adressen unterhalb 512MB gestückelt.

Wenn ein Programm mittels der Funktion malloc() Speicher alloziert, wird dieser von OS/2 standardmäßig aus den ersten 512 MB des virtuellen Adreßraums zur Verfügung gestellt. Seit dem Aufkommen der 4.5-Kernel (1998) können unter OS/2-Programme speziell so kompiliert werden (bei Verwendung von DosAllocMem() mit dem Parameter OBJ_ANY), daß auf den hohen Speicherbereich (die sog. high memory arenas, »HMA«) zugegriffen wird. Dieser virtuelle Adreßraum oberhalb 512 MB kann allerdings nicht von gewöhnlichen Anwendungen geteilt werden und ist für 16-Bit-Programme und -DLLs nicht erreichbar.

Zusammenfassungen für private und gemeinsame Objekte

Wenn ein Prozeß neuen Speicher anfordert, wird ihm von OS/2 ein Speicherobjekt mit bestimmten Eigenschaften alloziert. Es verfügt über eine Start- und Endadresse im virtuellen Adreßraum, ist oft verknüpft mit einer Datei und kann als gemeinsam genutzt oder privat definiert werden. Die Adressen können (zum Teil) zugesichert, im Speicher oder auch ausgelagert sein.

Die Zusammenfassungen für die Objekte sind interessant, da sie auch virtuelle Adressen im hohen Speicher (hex 2000 0000 und höher) aufweisen. Die zuvor bereits beschriebene Speichernutzung konzentriert sich mehr auf die gestückelten Speicheradressen (< 512 MB), die auch in der LDT ersichtlich sind.

Unter Process > Private Object Summary können Sie die Speicherobjekte des ausgewählten Prozesses in den privaten Regionen anschauen. Ich habe hier den kleinen Prozeß GSVDAEMN ausgewählt, der im Rahmen von APM verwendet wird.

Private Object Summary for 'GSVDAEMN':
  Object Allocated Committed   Present   Swapped
 address    memory    memory    memory    memory  Description
00010000  00010000  00001000  00001000  00000000  GSVDAEMN #0000 (shared data)
00020000  00010000  00003000  00003000  00000000  GSVDAEMN #0000 (private)
00030000  00010000  00002000  00002000  00000000  User Environment (hmte)
00040000  00010000  00001000  00001000  00000000  Thread Information Block (hmte)
00050000  00010000  00001000  00001000  00000000  stack (hmte [system owner])
00060000  03FA0000                                 Free
20000000  08000000                                 Free
          --------  --------  --------  --------
Totals:   00050000  00008000  00008000  00000000  (in bytes)
               320        32        32         0  (in Kbytes)
             0.313     0.032     0.032     0.000  (in Mbytes)
Number of objects = 5.
Analysis of 'Free' areas:
There are 2 free blocks which total 0BFA0000 (196224K or 191.625M)
The largest 2 free areas are:
 address      size
20000000  08000000 (131072K or 128.000M)
00060000  03FA0000 (65152K or 63.625M)

Die niedrige, private Region beginnt bei hexadezimal 0001 0000. Sie enthält die EXE-Datei, die Benutzerumgebung, Threadinformationen, den Stapel (stack) sowie die niedrigen und hohen Speicherregionen. Größere Prozesse weisen auch privaten Speicher auf, der für DLLs alloziert wurde. Die hohe private Region beginnt bei hexadezimal 2000 0000 (512 MB).

OS/2 reserviert ein Minimum von 64 MB privaten Speichers je Prozeß. Im hohen virtuellen Speicher wurde hier noch ein 128 MB Block reserviert, den unser »traditionelles« GSVDAEMN allerdings nicht ansprechen wird.

Unter Process > Shared Object Summary wird die gemeinsame Region des Programms veranschaulicht. Die allozierte Menge an gemeinsam genutztem Speicher von GSVDAEMN.EXE ist enorm. Selbst das kleinste OS/2-Programm partizipiert hier am allozierten Speicher von DLLs, die von anderen residenten OS/2-Anwendungen in die gemeinsam genutzte Region gestellt wurden. Daher ist die Liste sehr lang und ich kann hier nicht alles anführen. Aber der Großteil gemeinsamen Codes und Daten wird überhaupt nicht verwendet (Committed memory: 0). In meiner Auswahl kommen eigentlich nur Teile der der OS/2-Systembibliothek DOSCALL1 dafür in Frage, im Speicher angesprochen zu werden.

Shared Object Summary for 'GSVDAEMN':
  Object Allocated Committed   Present   Swapped
 address    memory    memory    memory    memory  Description
08650000  0E0E0000                                 Free
16730000  00010000  00000000  00000000  00000000  PMCTLS   allocated it
16740000  000B0000  00000000  00000000  00000000  THESEUS4 allocated it
167F0000  00080000  00000000  00000000  00000000  PMMERGE  allocated it
16870000  00070000  00000000  00000000  00000000  PSCRIPT  #0001 (shared code)
...........not shown part of the lower shared arena.....................
1FFD0000  00010000  0000E000  0000E000  00000000  DOSCALL1 #0000 (shared data)
1FFE0000  00010000  0000E000  0000E000  00000000  DOSCALL1 #0000 (shared data)
1FFF0000  00010000                                 Free
31B70000  2C1F0000                                 Free
5DD60000  00080000  00000000  00000000  00000000  INNOWIN  allocated it
5DDE0000  00200000  00000000  00000000  00000000  INNOWIN  allocated it
5DFE0000  02000000  00000000  00000000  00000000  FT2LIB   allocated it
5FFE0000  00020000  00000000  00000000  00000000  DRIVER   #0000 (]
          --------  --------  --------  --------
Totals:   0BB50000  010A2000  009B7000  00000000  (in bytes)
            191808     17032      9948         0  (in Kbytes)
           187.313    16.633     9.715     0.000  (in Mbytes)
Number of objects = 1108.
Analysis of 'Free' areas:
There are 4 free blocks which total 3A2F0000 (953280K or 930.938M)
The largest 4 free areas are:
 address      size
31B70000  2C1F0000 (722880K or 705.938M)
08650000  0E0E0000 (230272K or 224.875M)
16B00000  00010000 (64K or 0.063M)
1FFF0000  00010000 (64K or 0.063M)

Hier beginnt die niedrige gemeinsame Region bei 0865 0000 (134,31 MB). Die untere Grenze hängt von der Größe des größten Prozesses in der unteren privaten Region ab. Daher ist die Grenze zwischen privater und gemeinsamer Region nicht fest. Da die gemeinsamen Regionen von allen Prozessen »gesehen« werden, zeigen große Prozesse wie Mozilla dieselben Werte an, wie sie auch von den kleinen Prozessen wie GSVDAEMN gemeldet werden. Die gemeinsame Region endet üblicherweise bei 1FFF FFFF (512 MB).

Vergleich der Speicherregionen für alte bzw. neue Kernel mit Unterstützung des hohen Speichers Abb. 5: Vergleich der Speicherregionen für alte bzw. neue Kernel mit Unterstützung des hohen Speichers

Die oberen 32 bis 64 MB der gemeinsamen Region sind für geschützte Systembibliotheken reserviert (DOSCALL1, den SESMGR von Security/2). Die gemeinsame Region kann demnach maximal 512 - 2*64 MB = 384 MB groß sein. Jedoch füllen Presentation Manager und die Workplace Shell bei Desktop-Systemen die gemeinsame Region bereits, bevor irgendein Programm vom Anwender selbst gestartet werden kann. Die meisten frisch hochgefahrenen OS/2-Systeme haben daher lediglich ca. 200 bis 300 MB freien (nicht allozierten) gemeinsamen Speicher zur Verfügung.

Unter Verwendung eines Netzwerks ist es wahrscheinlich sogar noch weniger. Beim Start eines sehr schnellen (mit 4 GB bestückten) Rechners haben die automatisch gestarteten Netzwerkprogramme vorübergehend derart viel virtuellen Speicher in der gemeinsamen Region während des Verbindungsaufbaus alloziert, daß der Start der WPS in die Hose ging, was sich durch deformierte Symbole und fehlenden Text äußerte. Das Verzögern der net use-Befehle oder die Reduzierung der Threads schuf dabei Abhilfe.

Das Paradoxe dabei ist, das ein solch schneller Zuwachs im virtuellen Speicher bei langsamen oder speicherarmen Rechnern so gut wie ausgeschlossen ist. Vor zehn Jahren gestattete ich mehr als 2048 Threads (obwohl ich die niemals genutzt hatte), und heute, in Zeiten von Gigabytes an Speicher, muß ich dem Hunger meiner Programme nach virtuellem Speicher zügeln, indem ich die Anzahl der erlaubten Threads und Prozesse einschränke.

Den Prozessen steht heute zwar mehr realer und virtueller Adreßraum zur Verfügung, jedoch dürfen sie gleichzeitig nicht zuviel virtuellen Speicher in der unteren Region benutzen…

Im obigen Fall ist der größte freie Block in der unteren gemeinsamen Region 224,875 MB groß (bei 0865 0000), was nicht schlecht ist. Allerdings kann dieser Block fragmentiert sein, was sich oft mittels Lineare Nutzung durch Prozesse ermitteln läßt.

Andere Hilfsprogramme geben unter Umständen höhere Werte für den freien virtuellen Speicher an, besonders wenn sie kleine freie Speicherobjekte mit in die Rechnung einbeziehen. Aber diese Krümel sind in der Praxis nur von geringem Nutzen, wenn die großen Speicherobjekte von speicherhungrigen Anwendungen vor der Tür stehen und um Einlaß bitten. Das ist dann der Moment, wo das Schild nicht genügend freier Speicher an die Tür gehängt wird.

Die Fragmentierung von linearem Adreßraum tritt sehr leicht dann auf, wenn Anwendungen und ihre DLLs geladen und/oder entladen werden. Der virtuelle Adreßraum verhält sich zunächst ähnlich dem HPFS, aber viele virtuelle Speicherobjekte tolerieren keine Fragmentierung. Nach einer Weile, vielleicht schon einer halben Stunde, vielleicht erst nach Tagen (abhängig von der Speichernutzung Ihrer Programme und Ihrem Klick-Verhalten) verschwinden die größeren freien Blöcke im Speicher, und die meisten OS/2-Systeme mit »viel RAM« zeigen die ersten Programmstartfehler aufgrund der Fragmentierung der gemeinsamen Speicherregion. Selbst wenn Sie sich durch das Schließen möglichst vieler Anwendungen eine Abhilfe erhoffen. Dann ist es an der Zeit, nicht gespeichertes zu speichern und einen Neustart durchzuführen.

In der oberen (hohen) gemeinsamen Region, die nicht von allen Prozessen verwendet wird, stehen noch 705,938 MB zur Verfügung (bei hex 31B7 0000). Die Chancen, daß unser veralteter GSVDAEMN dort irgendwas verwendet, stehen schlecht. Selbst die für die Verwendung von hohem Speicher speziell kompilierten Mozilla-Produkte benutzen diese Regionen hauptsächlich nur für den Schriftarten-Cache der Innotek Font-Engine oder den von Windows abgeleiteten Flash-Code.

Dies ist aber keinesfalls ein Fehler der Entwickler. Sie tun, was in ihrer Macht steht und verwenden den Parameter OBJ_ANY in DosAllocateMem() oder die Linker-Option -Zhigh-mem von GCC, damit OS/2 ihren Code und die Daten in den hohen Speicher laden kann. Ob der OS/2-Loader das allerdings auch tatsächlich macht, steht auf einem anderen Blatt und ist abhängig von der jeweils gerade vorliegenden Speichersituation. Denn: Der OS/2-Loader darf aufgrund OBJ_ANY die Objekte (OBJ) nun »nach überall« hin (ANY-where) laden… Zitat:

Der gesuchte Parameter lautet


    

Beachten Sie, daß es sich hierbei eher um einen Hinweis als um eine Garantie handelt. Es bedeutet, daß das Betriebssystem versucht, den Speicherbedarf aus dem hohen Speicher (HMA) zu decken, jedoch den unteren Speicher verwendet, falls ersteres nicht möglich ist. Bedenken Sie auch, daß jeglicher allozierter Speicher (gemeinsam genutzt oder nicht) dann von vielen APIs nicht mehr verwendet werden kann (von allem, was einen 16-Bit-Umbruch erfordern könnte).

OS/2-Kernel-Verantwortlicher Scott E. Garfinkle (am 20. Nov. 1998) in comp.os.os2.misc

Tabellen für private und gemeinsame Speicherregionen

Diese Tabellen enthalten mehr technische Informationen. Ich überspringe hier die Beschreibung, da diese Regionentabellen wohl wahrscheinlich nur von Technikern und Entwicklern interpretiert werden können (wovon ich keines bin). Ich habe dazu nur zwei Anmerkungen.

Speicherobjekte, denen linearer Adressraum zugeordnet wurde, können durch einen HAR angesprochen werden. Wenn man solche Handles (Zugriffsaliase) verwendet, ist es nicht erforderlich, die exakte lineare Speicheradresse zu kennen.

Zu erwähnen wäre auch, daß Speicherobjekte im geschützten Modus (protected mode) alle Arten von Attributkennern besitzen können: Beschreibbar, lesbar, ausführbar, Datenbereich oder überwacht, um nur ein paar zu nennen. Dies ist Bestandteil der Mechanismen zum Zugriffsschutz.

RAM-Verwendung der Prozesse

Einen Überblick über die tatsächliche Speicherbelegung (real memory consumption) von privaten und gemeinsamen Regionen Ihrer Programme erhalten Sie mit Theseus > System > RAM usage by Process.

Was hier gemessen wird, ist die Menge an zugesichertem Speicher. Zugesicherter virtueller Speicher wird einer physischen Speicheradresse zugeordnet oder temporär in die SWAPPER.DAT ausgelagert. Aus diesem Grund ist der eigentliche Besitzer des Speichers nicht der Prozeß, sondern das System.

Programme im geschützten Modus können auf die virtuellen Adressen, die physischem Speicher zugeordnet wurden, nur vorübergehend zugreifen. Das geschieht dann, wenn OS/2 dem jeweiligem Programm Zeitscheiben des Prozessors zuteilt. Während der Ausführung des Programmcodes überwacht der Prozessor dessen Nutzung des virtuellen Speichers. In der Zeit dazwischen (und ganz bestimmt auch, wenn der aktive Theseus ihn mißt) gehört der potentiell gefährliche Programmcode im RAM dem System:

Memory from Physical address 7F97E000 for 100 bytes for process 'system':
Disassembly being done for 32-bit code.
7F97E000 (0000)00 83 EC 0C BA 8A *......* add [ebx+8ABA0CEC],al
7F97E006 (0006)00 00 *..* add [eax],al
7F97E008 (0008)00 E8 *..* add al,ch
7F97E00A (000A)42 *B* inc edx
7F97E00B (000B)00 00 *..* add [eax],al
7F97E00D (000D)00 83 C4 10 5E 5F *....^_* add [ebx+5F5E10C4],al

Wenn Sie in der Übersicht »RAM-Verwendung der Prozesse« (RAM usage by process) auf eine der grünen Adressen klicken, wird es immer darauf hinauslaufen, daß der Speicherbereich dem System gehört. Ungeachtet dessen mißt Theseus hier die Menge an zugesichertem Speicher, den sich ein Prozeß vom System ausgeliehen hat.

In speicherarmen Systemen sollte die Größe des physischen Speichers eines Prozesses in etwa dessen Arbeitsbedarf entsprechen. In Systemen mit viel Speicher jedoch wird deren Zuwachs eingeschränkt durch den nutzbaren virtuellen Adreßraum. Wenn Sie 1 GB RAM haben und es nicht genügend nutzbaren linearen Adreßraum in der begrenzten gemeinsamen Region mehr gibt, kann den Programme kein neuer Speicher mehr zugesichert werden und sie versagen ihren Dienst oder werden instabil.

Passen Sie also auf Programme auf, die sich viel Speicher zusichern lassen wollen. Besonders, wenn es sich um Speicher aus der gemeinsamen Region handelt, den auch ander Programme benutzen müssen.

Unter Misc > Content update können Sie dazu Start Periodic Update verwenden. Die Aktualisierungsfrequenz läßt sich unter Misc > Content Update > Options einstellen. Wir werden jetzt die zunehmende Speichernutzung von bestimmten, schnell anwachsenden Programmen beobachten.

Die wachsende Workplace Shell

Die Workplace Shell (bzw. deren Speicherbedarf) wächst aufgrund zunehmender Zugriffe auf WPS-Bibliotheken und Systemordner. Bei Verwendung von checkini wuchs meine WPS von ca. 12 MB auf 35 MB. Einmal angesprochen, bleiben der Code und die Daten im virtuellen Speicher, selbst wenn die WPS-Erweiterungen und -Ordner wieder geschlossen wurden.

Das ist kein Speicherleck, sondern ein Umstand der Architektur. Die Idee dahinter war, daß das Vorhalten von DLLs im virtuellen Speicher schneller war, als deren Laden vor (und Entladen nach) Benutzung. Das Öffnen eines Ordners mit vielen Objekten würde viel schneller gehen, wenn die Ordnerinhalte im virtuellen Speicher vorgehalten würden. Auf Systemen mit geringem physischem Speicher (16 MB entsprachen in 1994 einem Spitzengerät) würden die unbenutzten virtuellen Speicherseiten nach kurzer Zeit bereits wieder aus dem virtuellen Speicher ausgelagert, für den Anwender unsichtbar und ohne spürbare Nachteile.

Heute kann man einen Mangel an nutzbarem virtuellem Adreßraum bereits auf Systemen finden, die 128 MB oder mehr installiert haben. Wenn die gemeinsam genutzten Speicherresourcen knapp werden oder die gemeinsam genutzte Region fragmentiert ist, kann die WPS unter Umständen nicht die Menge an virtuellem Speicher reservieren, die sie für eine einwandfreie Funktion benötigt.

Dann ist es an der Zeit, einen WPS-Reset durchzuführen (eCS > Restart WPS oder [Strg-Alt-Entf] > WPS neu starten), um die Nutzung virtuellen Speichers durch die WPS auf den Anfangswert zurückzusetzen.

Wenn eine frisch gestartete WPS immer noch zu viele DLLs in den virtuellen Speicher lädt, sollten Sie unbenötigte WPS-Klassen und deren DLLs deregistrieren. In eCS finden sich beispielsweise immer noch die WPS-Klassen des IBM Global Network (AdvDialer, AdvUser, AdvAccount, AdvReg und AdvCust).

Die Mozilla-Familie

Programme der Mozilla-Familie (Mozilla, Firefox, Seamonkey, Thunderbird, NVU) erfordern massenhaft virtuellen Speicher - und viel davon wird im RAM behalten. Beim Start benutzt Mozilla bereits 18 MB virtuellen Speicher im RAM. Und das ist schon mehr, als eine frisch neu gestartete WPS benötigt. Während des Browsens kann Mozillas Speicherbedarf dann allerdings noch um einiges zunehmen.

Memory utilization display for Mozilla using 300 MiB Abb. 6: Anzeige der Speichernutzung für Mozilla und seine 300 MB

Mittels Theseus > RAM Usage by Process konnte ich Werte um 300 MB und mehr für Firefox messen.

Ein auf 2 GB beschränkter Speicher war nicht mein Problem. Selbst mit 512 MB wäre es immer noch kein Problem gewesen, da OS/2 ja die SWAPPER.DAT hätte benutzen können. Die wirkliche Gefahr ist schlicht fehlender virtueller Speicher in der gemeinsam genutzten Region.

Mit solchen Werten sollte der Großteil von Programmcode und Daten in privatem Speicher abgelegt werden – vorzugsweise in den hohen Regionen (HMA). Und tatsächlich war der größte Teil des Codes privat - und viel davon wurde auch »hoch«geladen. Das läßt sich mit System > Linear usage by process oder Process > Private Object Summaries und Process > Shared Object Summaries überprüfen.

Aber Firefox alloziert auch mindestens 318 MB privaten virtuellen Speicher in der unteren Region, wie sich mittels Process > Memory Utilization feststellen ließ. Und bedenken Sie, daß Speichernutzung nur den Teil mißt, der für alle (16- und 32-Bit-) Prozesse und DLLs erreichbar ist: Adressen unterhalb von 512 MB (hex 2000 000).

Obwohl sogar das meiste des Speichers privat war, gingen doch die »wenigen« 10% (hex 025E 0000, 38 MB) des unter 512 MB allozierten bereitgestellten gemeinsamen Speichers (originated shared memory) zu Lasten meiner laufenden WPS (45 MB).

Und die 13EB 0000 (318 MB) an privatem Speicher in der unteren Region haben genügt, um die Größe meiner gemeinsam genutzten Region auf 512 - 318 = 194 MB schrumpfen zu lassen (da der größte Prozeß in der privaten Region die Untergrenze der gemeinsam genutzten Region bestimmt). Somit ist das Allozieren von privatem Speicher nicht immer harmlos.

318 MB – da kann man sich natürlich wundern, warum das so ist, denn die Mozilla-Portierer geben ihr bestes, um so viel Code wie nur irgend möglich in den hohen Speicher zu laden.

Im Falle von Mozilla habe ich herausgefunden, daß das Zurücksetzen seines Speicher- und Festplattencache auf 0 keine Auswirkungen auf seinen Speicherhunger hatte. Die Speicherleckdiagnose (Memory Leak Detection) zeigte mir, daß Mozilla nur ganz selten Speicher wieder freigibt.

Firefox und Seamonkey halten es genauso. Und auch Thunderbird wächst beim Browsen von Newsgroups und Mail-Servern. Sie alle wachsen und wachsen, bis man ihre EXE-Dateien beendet und wieder neu startet.

Das Auslagern von inaktivem Code und/oder Daten durch den Physical Memory Manager auf die Platte ist das normale Verhalten von klassischen WPS- und PM-Applikationen, aber die Vertreter der Mozilla-Familie lagern nur sehr selten und sehr wenig Speicher auf Platte aus. Und erneut fragte ich mich warum.

Vielleicht wird das in einigen Fällen durch animierte GIFs oder Flash-Inhalte verursacht, die die Aufmerksamkeit des Anwenders erhaschen wollen oder durch die kontinuierliche Schriftaufbereitung beim Laden und Darstellen von Webseiten. Interaktive Webseiten benötigen RAM und Prozessorzeit selbst dann, wenn sie sich gerade nicht in aktiven Tab des Browsers befinden oder sie in einem der virtuellen Fenster des XPager liegen. Doch selbst dann sollte die exzessive Nutzung von physischem und virtuellem Speicher enden, sobald die Fenster mit interaktivem Inhalt geschlossen wurden. Die Prozessornutzung endet dann zwar auch, jedoch nicht die Speicherbelegung – dies ist erst dann der Fall, wenn Mozilla beendet wird. Es scheint also wirklich so zu sein, daß Mozilla Speicher nur selten während der Laufzeit wieder freigibt.

Und das ist das Hauptproblem, wenn man 1 GB RAM hat und zusätzlich noch OpenOffice und andere Programme in die gemeinsam genutzte Region laden möchte. Da unter Umständen kein adressierbarer virtueller Speicher mehr zur Verfügung steht, erscheinen die eingangs besprochenen Fehlermeldungen nicht genügend freier (virtueller) Speicher und die unerwarteten Fehlfunktionen anderer Programme.

Damit endet der erste Teil unseres Artikels zu Theseus und der Thematik zu OS/2 und dessen Speichermechanismen. In der nächsten Ausgabe schließen wir die Betrachtung von Theseus ab und werfen unter anderem einen Blick auf die Speicherleckdiagnose.

Übersetzung: Thomas Klein
Formatierung: Christian Hennecke
Korrektur: Karl-Heinz Markus
Daten und Quellen

Speicheranalyse in OS/2 von Greg Shaw (engl.): http://www.goldencode.com/atlos2/notes/theseus/memoryanalysis.html
Speicher-Debugging für C und C++ Programme (10. März 1994) von Steve Hargis und Mike Skelton (engl.; IBM, Austin, Texas): In memlks.zip (postscript).
Benutzung der hohen Speicherregion in OS/2 - aus The Russian Electronic Developer Magazine: http://os2.in.ru/rdm2/articles/highmem/index.html