Speicherleaks im Agent Manager

  • Hallo allerseits,


    direkt vorweg: Ich bin mir nicht sicher, in welches Forum dieses Thema am besten passt, da es hier sowohl um Entwicklungsaspekte als auch um administrative Aspekte geht. Irgendwie ist von beiden etwas dabei. Aber zur Not lässt sich das Thema ja immer noch verschieben. Nun aber zum Thema...


    Letzte Woche habe ich mich über den Speicherbedarf des Agent Managers, besser gesagt des Prozesses namgr.exe, gewundert. Seit ich meinen Java-Agenten auf dem Server laufen ließ wuchs der Speicherbedarf stetig an und wurde nicht mehr kleiner. Dies hatte dann schlussendlich zur Folge, dass der Agent Manager sich aufhing und nicht mehr reagierte. Da half nur noch den Server durch zu starten.


    Nachdem ich dazu meine Bibel (Java unter Lotus Domino) konsultiert hatte stellte ich fest, dass ich bisher einen eklatanten Fehler begangen hatte. Ich erfuhr, dass ich als Java-Programmierer für Lotus Notes / Domino auch dafür Sorge zu tragen habe, dass die von mir ins Leben (bzw. in den Speicher) gerufenen Domino Objekte auch wieder freigegeben werden. Das hatte ich garnicht getan. Da war es kein Wunder, dass der Speicherbedarf des Agent Managers zusehends wuchs bis er schließlich die Segel strich.


    Naja, aus Fehlern lernt man. Die Aufgabe mit dem Freigeben des Domino Objekte in meinem Code habe ich sofort nachgeholt und meinen Code mehrmals genau geprüft, damit sich ja kein Speicherleak mehr irgendwo versteckt. Was das anbelangt, sollte mein Agent nun wirklich 100%'ig sauber sein. Alle benutzen Domino Objekte gebe ich sofort nach Gebrauch auch wieder ordnungsgemäß frei.


    "Nun sollte sich das mit dem Speicherproblem doch eigentlich gelöst haben" sagte ich mir. Aber leider besteht das Problem immer noch. Wenn ich den Server starte und mir den entsprechenden Prozess im Taskmanager ansehe belegt dieser ~7,3 MB. Starte ich dann ein mal meinen Agenten und betrachte dabei den Speicherbedarf des Prozesses so sieht man, wie dieser bis zum Ende der Laufzeit des Agenten um ~30 MB anwächst. Nachdem der Agent beendet wurde (bzw. er zuende gelaufen ist) sollte doch der Speicherbedarf des Prozesses wieder auf die ursprünglichen ~7,3 MB zurückgehen, denn wofür gebe ich sonst meine Objekte wieder frei? Leider aber bleibt bei Ende der Laufzeit des Agenten der Speicherbedarf unverändert auf dem hohen Level. Starte ich den Agenten erneut steigt der Speicherbedarf nochmals um ~30 MB und bleibt nach Ende der Laufzeit des Agenten wiederum auf dem Hohen Level stehen.


    Somit kann ich meinen Agenten ca. vier Mal starten und bis zu Ende laufen lassen. Spätestens beim fünften Mal stirbt dann der AgentManager ab bzw. er bleibt hängen. (Speicherbedarf dann um die 150 MB)


    Jetzt frage ich mich: Woran kann das liegen ? Ist es vielleicht sogar normal, dass der Speicherbedarf des Agent Managers nach Ende der Laufzeit eines Agenten nicht zurückgeht ? Vielleicht können hierzu andere Entwickler Stellung nehmen, die mehr Erfahrung haben als ich.


    Danke auf alle Fälle schon mal im Voraus, auch dafür, dass Ihr bis hier hin im Text nicht schon längst das Interesse verloren habt.


    MfG


    Leon

  • Habe heute mit Entsetzen feststellen müssen, dass die Domino-Objekte scheinbar trotz Aufruf der recycle() Methode nicht recyclet werden. Ich habe einfach mal ganz zum Schluss meines Agenten, also nachdem alle verbleibenden Domino-Objekte (inkl. der Session) in einem finally-Block dem Recycling zugeführt wurden, nochmal auf die Session zugegriffen und mir auf der Konsole den Namen ausgeben lassen unter dem die Sessen lief / läuft. Eigentlich hätte ich hier eine Exception "Object has been removed or recycled" erwartet, aber man sehe und staune: Die Ausgabe funktioniert immer noch, obwohl die Session schon garnicht mehr hätte existieren dürfren. Wenn also das Recycling garnicht funktioniert ist es kein Wunder, dass der Speicher nicht freigegeben wird.


    Was nun ?


    MfG


    Leon

  • In der Java-Doku von Sun hab ich mal gelesen, dass weder die destroy- noch die finalize-Methoden wirklich Speicher freigeben. Es wird alles über den Garbage Collector gesteuert, der seine ureigene Mimik hat. In der Doku stand, dass ein "best effort" gemacht wird beim Aufruf des Garbage Collectors, dass man sich also nicht wirklich drauf verlassen sollte...


    /edit:
    Sorry, hatte vorhin nicht den Link zur Hand und keine Zeit, zu suchen. Hier nun die Erklärung zu System.gc() aus Sun's eigener Java-Doku. Und IBM schreibt, dass ihre VM Sun's Kompatibilitätstests bestanden hat, also muss das wohl so...

    Life is not a journey to the grave with the intention of arriving safely in a pretty and well-preserved body, but rather to skid in broadside, thoroughly used up, totally worn out, and loudly proclaiming "Wow, what a ride!!! :evil:
    Beschleunigung ist, wenn die Tränen der Ergriffenheit waagrecht zum Ohr hin abfliessen - Walter Röhrl

  • Hallo RockWilder,


    besten Dank für Deine Antwort.
    Der Garbage Collector ist auch nicht das Problem, denn dieser kommt an die eigentlichen Domino-Objekte ja überhaupt nicht ran. Alles was dieser freigeben kann sind die Java-Wrapper-Klassen, welche den Zugriff auf die dahinterliegenden und in C++ realisierten Objekte regeln.


    Genau das war ja auch mein anfänglicher Fehler, von dem ich im Top-Post berichtet habe. Ich bin davon ausgegangen, das der Garbage Collector die Domino-Objekte vollständig auflöst sobald die letzte Referenz auf das jeweilige Objekt gelöscht wurde. Da die Domino Java API aber unter'm Strich nichts anderes ist als eine Bibliothek von Wrapper-Kalssen, welche sich mit Hilfe der JNI um die plattformübergreifenden C++ Klassen legen, kann der Garbage Collector diese Objekte jedoch garnicht selbstständig auflösen, denn er weiß nicht einmal etwas von deren Existenz. Aus diesem Grund bringt jede Domino Java Klasse eine recycle() Methode mit, mit der man das in C++ implmentierte Objekt im Speicher freigeben kann.


    Über Amazon kann man inzwischen prima online in Büchern stöbern. Daher hier einmal das entsprechende Kapitel über Recycling von Java Domino Objekten in meiner "Bibel".


    Die eigentliche Frage die ich mir nun stelle ist, wieso die Objekte trotz ordnungsgemäßem recycling im Code trotzdem nicht freigegeben werden ?


    MfG


    Leon

  • Okay, es ist wohl an der Zeit für einen Statusbericht.


    In der Zwischenzeit hatte ich Gelegenheit noch etwas zu Testen. Dabei habe ich herausfinden können, dass es wohl so ist, dass ich auch die Dominoobjekte freigeben muss, die ich selbst garnicht ins Leben (bzw. in den Speicher) gerufen habe, wie die Session oder aber auch den AgentContext. Dabei spielt es keine Rolle, ob ich diese im Laufe des Agenten überhaupt benötige oder referenziere. Man muss auf jeden Fall mind. die Session und den AgentContext recyclen, selbst wenn man diese garnicht braucht innerhalb des Agenten. Somit war mein Agent doch noch nicht so sauber wie ich dachte. Wobei man ja eigentlich davon ausgehen sollte, dass derjenige der die Objekte erstellt auch für deren Zerstörung zuständig ist. In diesen Fall überlässt Domino jedoch uns die Pflicht zur Säuberung.


    Nun habe ich es zumindest soweit geschafft, dass der Agent nach dem ersten Lauf ~25 MB Speicher für sich beansprucht und nach jeden weiteren Lauf ~200 KB mehr. Irgrendwo scheint da also immer noch eine unsaubere Stelle zu sein, nur habe ich diese noch nicht lokalisieren können.


    Mir ist jedoch noch etwas echt verrücktes aufgefallen: Wie gesagt steigt der Speicherbedarf des namgr.exe Prozesses nach dem Ersten Lauf auf ~25 MB und nach jedem weiteren Lauf um ~200 weitere KB. Dies lässt sich im Taskmanager des Servers sehr schön mitverfolgen. Man kann den Taskmanager schließen und wieder öffnen, der Speicherbedarf ändert sich nicht. Man kann sich auch am Server abmelden (also die Windows Session) und wieder anmelden, der Speicherbedarf ändert sich auh so nicht. Die Konsole des Domino Servers ist dabei stets auf dem Desktop zu sehen. Aber jetzt kommt's: Öffnet mal den Taskmanager, so dass Ihr den bzw. die namgr.exe Prozesse und deren aktuellen Speicherbedarf sehen könnt, und minimiert dann einmal das Domino Konsolenfenster. Einfach nur in die Taskleiste minimieren. In diesem Augenblick sinkt der Speicherbedarf des namgr.exe Prozesses auf wenige KB (~700 KB). Nun kann man das Konsolenfenster wieder auf den Desktop holen und der Speicherbedarf bleibt ach auf dem niedrigen Level. Jedoch nur solange, bis wieder ein Agent läuft. Dann steigt der Speicherbedarf wieder auf den Level, den er auch ohne diese Aktion erreicht hätte, d.h. die Größe von vor der Minimieraktion + ~200 KB.


    Wie aber kann ich mir dieses Verhalten mit dem regelrechten Einbruch des Speicherbedarfs beim Minimieren der Dominoonsole erklären ?


    Ich installiere mir gerade einmal testweise einen Domino R6.5 Server um das ganze auch mal dort zu testen. Gerade in Sachen Recycling von Dominoobjekten soll sich da ja einiges getan haben.


    Würde mich sehr interessieren, ob auch andere dieses Verhalten mit dem Minimieren der Dominokonsole beobachten können. Bitte um Feedback.


    MfG


    Leon

  • Mit besten Grüßen aus Redmond

    Life is not a journey to the grave with the intention of arriving safely in a pretty and well-preserved body, but rather to skid in broadside, thoroughly used up, totally worn out, and loudly proclaiming "Wow, what a ride!!! :evil:
    Beschleunigung ist, wenn die Tränen der Ergriffenheit waagrecht zum Ohr hin abfliessen - Walter Röhrl

  • Hallo RockWilder,


    danke für die Aufklärung des Phänomens. Das erklärt zumindest das Verhalten beim Minimieren der Dominokonsole. Wie beurteilst Du denn das allgemeine Speicherverhalten des Agent Managers, so wie ich es oben in meinem letzten Post beschrieben habe? Ich bin doch sicher nicht der Erste, der einen Java-Agenten unter Domino R5.0.13a laufen lässt!? Ich verfüge halt noch nicht über die Menge an Erfahrung um dies beurteilen zu können.


    MfG


    Leon

  • Kann ich nicht beurteilen. Gott sei Dank weigern sich unserer Entwickler standhaft, Java-Agenten zu schreiben, das ist alles noch das gute alte LotusScript, was schon immer funktionierte und nicht nachträglich drangeflanscht wurde. Und von Java weiß ich persönlich nur 2 Dinge: so etwas gibt es und mehr will ich nicht wissen.


    Die spannende Frage, die sich mir sowieso stellt: warum willst du unbedingt einen Java-Agenten? Ich bin kein professioneller Entwickler und die 5er Version ist nicht (mehr) meine starke Seite. Aber was hat Java, was LS nicht hat? Und warum die schon lange nicht mehr supportete 5er Version?


    Ich meine, eines muss klar sein: die Java-VM ist eine zusätzliches Stück Software, das Ressourcen frisst. Diese Software zu starten, obwohl ich die selbe Funktionalität auch anders bekäme, das erschließt sich mir nicht. Ich vermute allerdings, du hast einen triftigen Grund dafür.

    Life is not a journey to the grave with the intention of arriving safely in a pretty and well-preserved body, but rather to skid in broadside, thoroughly used up, totally worn out, and loudly proclaiming "Wow, what a ride!!! :evil:
    Beschleunigung ist, wenn die Tränen der Ergriffenheit waagrecht zum Ohr hin abfliessen - Walter Röhrl

  • Da LotusScript in der Lage ist, über Deklarartionen auch direkt auf Funktionen in der Notes (C)API zuzugreifen hast Du schon Recht; LotusScript ist schon sehr mächtig und man kann eine ganze Menge damit umsetzen. In aller Regel ist man so auch nicht auf Java angewiesen. Zudem unterstützt LotusScript auch noch den COM Standard, welcher nochmals eine ganze Reihe an Möglichkeiten bietet. Leider habe ich jedoch noch nicht so wirklich viel Erfahrung in der Entwicklung unter LotusScript, dafür jedoch in der Entwicklung unter C/C++ und Java. In meinem Projekt geht es hauptsächlich darum, Daten aus unserem unter Domino laufenden CRM-System mit dem Bundeszentralamt für Steuern abzugleichen. Hierzu müssen u.a. HTTP-Verbindungen aufgebaut, XML-Daten verarbeitet und die Daten entsprechend aufbereitet werden. Das geht unter Java sehr komfortabel. Ob man das auch unter LotusScript hätte machen können möchte ich garnicht bezweifeln.


    Wieso weigern sich Eure Entwickler denn so strikt dagegen, Agenten unter Java zu entwickeln? Soweit ich das bisher mitebekommen habe, ist IBM doch so derbe stolz darauf, dass Ihre Applikationen so gut mit Java können !?


    MfG


    Leon

  • Ja ist IBM schon, aber eigentlich erst ab Version 6.
    Unter 5 war Java halt da aber es hat niemand ernsthaft genutzt.
    Daher kann ich mir gut vorstellen, daß es da auch nie wirklich aufgefallen ist wenn es sich wie bei dir beschrieben verhält.


    Außerdem arbeitet 5 auch noch mit dem JDK 1.1 welches meines Wissens nach auch noch einige Macken hatte (auch was Speicherfreigabe angeht).
    Kann also gut sein, daß es nichtmal an Notes sondern an der Java Version selber liegt.


    Und wie RockWilder schon sagte: Eure Version ist schon lange nicht mehr supportet also wird sich da auch nichts mehr ändern

  • Wir werden auch wahrscheinlich irgendwann in den kommenden Monaten (vielleicht schon im August) auf Domino R7 wechseln. *jubel* Mit Java 1.1.8 arbeiten zu müssen ist in der Tat schon eine sehr (!) große Einschränkung. Neben der Tatsache, dass sich in Sachen Speichermanagement wohl viel verbessert haben soll in den Folgeversionen, hat man bei den meisten offenen Java Bibliotheken / Projekten wie z.B. bei JTDS auch das Problem, dass dort unterhalb von Java 1.2 schonmal garnichts läuft.


    In diesem Sinne kann ich meine Kollegen da draußen schon verstehen, wenn Sie einen Agenten für Domino R5 lieber unter LotusScript als unter Java Entwickeln. Voraussetzung ist dabei natürlich auch die entsprechende Erfahrung in LotusScript.


    Wie ist das denn heute? Sträuben sich die Entwickler, die unter Domino R6.5 / R7 (vielleicht sogar schon unter R8) entwickeln, immer noch so rigoros gegen den Einsatz von Java? Oder bezog sich das auf Domino R5? Was die Performance von Java angeht hat sich gegenüber damals ja inzwischen sehr viel getan, so dass man dies wohl kaum noch als ernsthaftes Kontra einbringen könnte.


    MfG


    Leon

  • Also meiner Erfahrung nach hängt das von mehreren Faktoren ab:


    - Was will man genau machen und wo ist es einfacher ?
    - Will man mehr Performance oder ist diese egal ?
    - Wo liegen die eigenen Kenntnisse ?
    - Verwendet man Schnittstellen, die nur in Java oder nur für Script verfügbar sind ?


    Man sollte halt Java nicht für Sachen vergewaltigen für das es einfach nicht gedacht ist.
    Genauso aber auch umgekehrt

  • Der größte Unterschied zwischen einem Java-Agenten und einem LotusScript Agenten ist denke ich der, dass ein Java-Agent stets im Background ausgeführt wird, während ein LotusScript Agent im Frontend läuft.

  • Zitat


    Leon schrieb:
    Der größte Unterschied zwischen einem Java-Agenten und einem LotusScript Agenten ist denke ich der, dass ein Java-Agent stets im Background ausgeführt wird, während ein LotusScript Agent im Frontend läuft.


    Das verstehe ich nicht, was du damit aussagen willst...


    Zitat


    Wie ist das denn heute? Sträuben sich die Entwickler, die unter Domino R6.5 / R7 (vielleicht sogar schon unter R8) entwickeln, immer noch so rigoros gegen den Einsatz von Java? Oder bezog sich das auf Domino R5?


    Es bezieht sich bei uns auf 6.5.5 und 7. Und bei uns ist es -Gott sei Dank- so, dass die Entwickler nicht einfach was zusammenklatschen können und gut ist. Wir haben da ein erhebliches Mitspracherecht. Und ich möchte auf meinen Maschinen kein Java-Müll. Wenn ein Entwickler daher kommt und stichhaltig begründet, dass sein Agent eben zwangsläufig Java sein *muss*, ok, da kann ich nix gegen tun. Aber das ist bisher noch nicht aufgetreten.
    Wie Matthias schon sagte, es hängt auch ein wenig von persönlichen Vorlieben und auch vom Skill ab. Leute, die seit 10 Jahren LS programmiert haben, die steigen nicht einfach aus Lust und Laune auf den allerneuesten Hype um. Die wissen, was sie können und sind echt gut darin, warum also das Rad neu erfinden und es dabei eckig machen?


    Zitat


    Was die Performance von Java angeht hat sich gegenüber damals ja inzwischen sehr viel getan, so dass man dies wohl kaum noch als ernsthaftes Kontra einbringen könnte.


    Es mag sein, dass neue Java-Versionen performanter sind, als ältere. Aber ich bezweifle ernsthaft, dass Java jemals so performant sein wird, wie nativ ausgeführte Kompilate. Sei es nun LS, sei es C/C++ oder was auch immer. Die prinzipbedingte Zwischenschicht frisst *immer* Ressourcen und muss daher *immer* langsamer sein. C# hat auch nicht die Performance wie C. Und für mich persönlich ist es ein erhebliches Kontra, wenn ich die Maschinen X Prozent größer dimensionieren muss, was sie Y Prozent teurer macht, nur damit Java drauf läuft, welches mir aber keinen Mehrwert bringt.

    Life is not a journey to the grave with the intention of arriving safely in a pretty and well-preserved body, but rather to skid in broadside, thoroughly used up, totally worn out, and loudly proclaiming "Wow, what a ride!!! :evil:
    Beschleunigung ist, wenn die Tränen der Ergriffenheit waagrecht zum Ohr hin abfliessen - Walter Röhrl

  • Ein Agent kann entweder im Frontend oder im Background ausgeführt werden. Im Frontend hat man Zugriff auf UI-Objekte wie z.B. den Workspace des ausführenden Benutzers oder die aktuelle Arbeitsumgebung. Das hat man im Background nicht. Und ein Java-Agent kann (meines Wissens nach) ausschließlich im Background ausgeführt werden, während ein LotusScript-Agent im Frontend läuft.


    Deine pure Abneigung gegenüber Java ist mir ehrlich gesagt etwas unverständlich. Natürlich hast Du Recht indem Du sagst, dass durch die JVM immer Leistungseinbußen entstehen. Aber bist Du Dir sicher, dass der Performanceunterschied zwischen einem LotusScript-Agent und einem Java-Agent wirklich so gravierend ist, gerade bei den aktellen Domino Versionen ? Gerade durch den JIT-Kompiler haben moderne Java-Applicationen heute kaum noch Leistungseinbußen gegenüber hart kompilierten Applicationen.
    Lass mich hierzu noch etwas aus meiner "Bibel" zitieren:


    Zitat

    Diese Java-Klassen sind lediglich Wrapper-Klassen, die über „native“ Referenzen auf die maschinenspezifischen C++ Klassen von Notes und Domino zugreifen. Diese Bibliotheken sind übrigens dieselben, auf die LotusScript zugreift, d.h. letztendlich ist die Verwendung der Domino-Klassen nicht nur ähnlich zu der Verwendung in LotusScript – so haben fast alle LotusScript Klassen einen Repräsentanten in Java und beide haben in der Regel eine äquivalente Signatur –, sondern faktisch rufen beide denselben C++ Code auf.


    Quelle: www.domino-java.com



    Zitat

    Und bei uns ist es -Gott sei Dank- so, dass die Entwickler nicht einfach was zusammenklatschen können und gut ist.


    Wie meinst Du das ? Was meinst Du mit "zusammengeklatscht"?


    Und ich habe noch nie davon gehört, dass man einen Server aufrüsten musste, nur weil jemand auf die Idee kam darauf einen Java-Agenten oder sonst irgend eine Java-Anwendung ausführen zu wollten. Da lass und bitte mal auf dem Boden der Tatsachen bleiben.


    Ich denke bei Dir ist es einfach die Skepsis gegenüber Java und der Grundgedanke "never change a running system". Neuerungen müssen jedoch nicht immer schlecht sein.


    MfG


    Leon

  • Natürlich greifen die Java Klassen auf die gleichen Routinen zu wie Lotus Script, aber um einen Java Agenten auszuführen muss grundsätzlich erst einmal die JVM gestartet werden. Diese benötigt alleine durch den Start schon Ressourcen, die ein Script Agent nicht benötigt.
    Und die Wrapper Klassen selber machen den Zugriff auf die Domino API Funktionen auch nicht schneller sondern langsamer, weil da eben noch mal eine Zwischenschicht ist.


    Insoweit hat RockWilder vollkommen Recht.


    Natürlich hat noch niemand davon gehört daß ein Server aufgerüstet werden musste weil ein Agent in Java geschrieben ist, aber hier macht es eben die Summe, d.h. wenn ihr jetzt alle Agenten in Java schreibt die ein anderer in Lotus Script schreibt, dann braucht euer Server auch bessere Hardware. Siehe die oben genannten Punkte.


    Und zu deinem Punkt Frontend/Backend solltest du das genauer ausdrücken, denn so wie du es ursprünglich beschrieben hast stimmt es nicht.
    Ich kann auch aus dem Client heraus einen Java Agenten starten, der an meinem aktuellen Dokument Änderungen vornimmt. Aber eben nur über die Backendklassen, allerdings im Frontend.

  • Ich habe ja auch nicht vor alle meine Agenten in Java zu entwicklen. Aber in diesem konkreten Fall schien mir Java die beste Wahl, zudem ich mit LotusScript selbst noch nicht wirklich über Erfahrung verfüge. Aber die möchte ich mir ja aneignen.


    MfG


    Leon

  • Eine Ursache hast du ja schon von RockWilder bekommen. Die andere ist eben das allgemeine Problem, daß die JVM bzw der Garbage Collector den Speicher recht willkürlich freigibt. Einfach gesagt dann wenn er Lust und Laune dazu hat. Teilweise auch erst beim beenden der JVM. Das habe ich vor allem bei den 1.1 Versionen feststellen können. Ist dann später etwas besser geworden.
    Da der Agent Manager aber beim Start die JVM startet und erst beim beenden des Agent Managers wieder beendet kann es eben ewig dauern bis der Speicher freigegeben wird.
    Bei einer schon recht stark ausgelasteten Maschine auch um einiges länger als bei einer die dauernd im Leerlauf ist

  • Wird eigentlich für jeden Java-Agenten eine separate Instanz der JVM aufgerufen, oder wird lediglich eine Instanz der JVM durch den Agent Manager erstellt, welche sich dann um alle folgenden Java-Agenten kümmert ?


    Wie gesagt stellen wir in der nächsten Zeit ohnehin auf eine aktuellere Version von Domino (und Notes) um. Ich hoffe, dass dort mein eigentliches Problem behoben sein wird.


    MfG


    Leon