Domino 9 und frühere Versionen > ND8: Entwicklung

Java Agent recyclen

(1/3) > >>

Matze84:
Guten Morgen zusammen!

Ich hab des öfteren Probleme mit der Speicherbelastung durch einen Java-Agent, der mit LotusNotes-Objekten arbeitet. Ich hab mir diverse Beiträge zum Recyclen von NotesObjekten durchgelesen und meines Erachtens diese auch in meinem Agenten umgesetzt, trotzdem habe ich im Vergleich zu der LotusScript Variante einen eklatant hörenen Speicherverbrauch (der auch nicht mehr freigegeben wird).

Ich verwende im Agenten einen eigenen Datentyp, der String-Objekte und ein Datums-Objekt aufnimmt.

Kann mir jemand sagen, ob ich das Recyclen richtig mache oder wo NotesObjekte die Referenz verlieren und weiterhin im Heap bestehen bleiben?

Gruß

Matthias


--- Code: ---mport java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import datentyp.LogEntry;
import lotus.domino.*;

public class JavaAgent extends AgentBase {

public void NotesMain() {

try {
//Globale Variablen
Session session = getSession();
Database db = session.getDatabase(session.getServerName(), "domlog.nsf");
Database dbCurrent = session.getCurrentDatabase();
View viewEinstellungen = dbCurrent.getView("(Einstellungen)");
Document docZusammenfassung, docProfilDokument, docTmp, docDomLog;
LogEntry logEntryTmp = new LogEntry();
HashMap<String, LogEntry> listLogEntries = new HashMap<String,LogEntry>(100000);
List<String> listDelete = new ArrayList<String>();
Name nameUsername = null;
DateTime dtErstesDoc, dtLogEntry, dtStichtag;
String strRequest, strTranslatedURI;
int intStatus, intZaehlerTageStay = 14, intZaehlerTageEdit = 1, intDifferenz;

//Profildokument auslesen (Anzahl der Tage die stehengelassen werden sollen
docProfilDokument = viewEinstellungen.getDocumentByKey("ProfileDocument");
if(docProfilDokument != null)
{
intZaehlerTageStay = docProfilDokument.getItemValueInteger("AnzahlTageStayNO");
intZaehlerTageEdit = docProfilDokument.getItemValueInteger("AnzahlTageEditNO");
}
docProfilDokument.recycle();
viewEinstellungen.recycle();

dtStichtag = session.createDateTime("01.01.2000");
dtStichtag.setNow();
dtStichtag.adjustDay(-intZaehlerTageStay);


for(int j=0; j<intZaehlerTageEdit; j++)
{  
//Collection aus allen Dokumenten in der domlog.nsf bilden
DocumentCollection collDoc = db.getAllDocuments();
docDomLog = collDoc.getFirstDocument();
if(docDomLog == null)
{
break;
}

dtErstesDoc = docDomLog.getCreated();
dtLogEntry = docDomLog.getCreated();
intDifferenz = dtStichtag.timeDifference(dtErstesDoc)/86400;


//Solange Dokumente von einem Tag vorhanden sind und diese nicht aufgrund der Eingabe aus dem
//Profildokument stehengelassen werden sollen
while(docDomLog != null && dtLogEntry.getDateOnly().equals(dtErstesDoc.getDateOnly()) &&  intDifferenz>= 0)
{
                /**
                   *Hier kommt weiterer Code, der jedoch keine LotusNotes Objekte verwendet
  */


//Erstes Dokument
if(listLogEntries.size() == 0)
{
LogEntry logEntry = new LogEntry(strSearchString, 1, dblContentLength,strUsername, strUseradresse, strZugriff,
strTranslatedURI, strServer, intStatus, dtLogEntry);
listLogEntries.put(strSearchString, logEntry);
}
//für jedes weitere Dokument
else
{
logEntryTmp = listLogEntries.get(strSearchString);
if(logEntryTmp != null)
{
//Es besteht bereits ein passender Eintrag
logEntryTmp.setIntAnzahlZugriffe(logEntryTmp.getIntAnzahlZugriffe()+1);
logEntryTmp.setDblContentLength(logEntryTmp.getDblContentLength()+ dblContentLength);
listLogEntries.put(strSearchString, logEntryTmp );
}
else
{  
//Es besteht noch kein passender Eintrag
LogEntry newLogEntry = new LogEntry(strSearchString, 1, dblContentLength,strUsername,   strUseradresse, strZugriff,
strTranslatedURI, strServer, intStatus, dtLogEntry);
listLogEntries.put(strSearchString,newLogEntry);
}
}

//dtLogEntry.recycle();
docTmp = collDoc.getNextDocument(docDomLog);
if(docTmp != null)
{
//dtLogEntry.recycle();
dtLogEntry =docTmp.getCreated();
}
listDelete.add(docDomLog.getUniversalID());
docDomLog.recycle();
docDomLog = docTmp;



}//Ende while-Schleife

//Schreiben der Dokumente
//######################################################################################################
for(Object value : listLogEntries.values())
{
logEntryTmp = (LogEntry) value;
docZusammenfassung = dbCurrent.createDocument();
docZusammenfassung.replaceItemValue("Form", "Datenbankzugriff");
DateTime datum = session.createDateTime(logEntryTmp.getDatum().getDateOnly());
docZusammenfassung.replaceItemValue("DatumDT", datum);
docZusammenfassung.replaceItemValue("UsernameTX", logEntryTmp.getStrUsername());
docZusammenfassung.replaceItemValue("UseradresseTX", logEntryTmp.getStrUseradresse());
docZusammenfassung.replaceItemValue("ServerTX", logEntryTmp.getStrServer());
docZusammenfassung.replaceItemValue("ZugriffTX", logEntryTmp.getStrZugriff());
docZusammenfassung.replaceItemValue("StatusNO", logEntryTmp.getIntStatus());
docZusammenfassung.replaceItemValue("TranslatedURITX", logEntryTmp.getStrTranslatedURI());
docZusammenfassung.replaceItemValue("AnzahlZugriffeNO", logEntryTmp.getIntAnzahlZugriffe());
docZusammenfassung.replaceItemValue("ContentLengthNO", logEntryTmp.getDblContentLength());
docZusammenfassung.save(true,true);
docZusammenfassung.recycle();
datum.recycle();
logEntryTmp.datum.recycle();
}
//#####################################################################################################
listLogEntries.clear();
dtErstesDoc.recycle();

for(int i=0; i<listDelete.size(); i++)
{
docTmp = db.getDocumentByUNID(listDelete.get(i));
docTmp.removePermanently(true);
docTmp.recycle();
}

} //Ende erste for-Schleife


//Recycle NotesObjekte
dtStichtag.recycle();
db.recycle();
dbCurrent.recycle();
session.recycle();
} catch(Exception e) {

e.printStackTrace();
}
}

--- Ende Code ---

Ralf_M_Petter:
Natürlich kann jetzt keiner deinen Code durchanalysieren, aber was auffällt ist dass du session recycelst, was man in einem Agent laut Doku auf keinen Fall machen solltest. Auf der anderen Seite sehe ich kein recycle für collDoc. Wie misst du denn den zusätzlichen Speicherverbrauch.

Grüße

Ralf

Matze84:
Danke für die Info!

Die Speicherbelastung lese ich an der Info aus dem DDM ab:

Agent Manager: Very High memory usage by agent 'XXX' in database 'XXX'. Threshold level Very High. Agent Owner: XXX'.

Diese Meldung bekomme ich beim LotusScript Agenten nicht

Ralf_M_Petter:
Hm vielleicht hat dein Problem überhaupt nichts mit Recycle zu tun. Du verwendest eine HashMap mit 100000 Einträgen. Keine Ahnung wie lange die LogEntry sind, die du da reinstellst. Aber wenn jeder LogEntry  z.b. 1024 bytes hat, dann reden wir hier alleine schon von 100 Megabyte an Daten. Die im Hauptspeicher liegen. Keine Ahnung wie hier die Threshholds sind. Aber ich denke mal, dass könnte dein Problem erklären.

Grüße

Ralf

Matze84:
Jedes LogEntry besteht aus 6 Strings,  3 primitiven Datentypen und einem DateTime-Objekt.  Ich denke der Speicherverbrauch dürfte sich in Grenzen halten.

Ich könnte mir vorstellen, dass eine DocumentCollection aus 3-4 Millionen Documenten eher ein Speicherproblem werden könnte

Navigation

[0] Themen-Index

[#] Nächste Seite

Zur normalen Ansicht wechseln