[Progress Communities] [Progress OpenEdge ABL] Forum Post: RE: OpenEdge 11.6 | How to find a memory leak on AppServer

Status
Not open for further replies.
T

Thomas Wurl

Guest
Yes! Just passing static dataset around should not be a / the problem ... How do you know that you have a leak on AS? Just a feeling? From what you are writing there may be some potential problems: - Soap and XML. You parser may leave X-DOC, X-NODEREF ... in memory. - Persistent procedures stay in memory... How do you pass the datasets to your .Net frontend? C# OpenClient Proxy? Do you call "sample.p" directly from .Net or do you have some kind of "service adapter"? To see what's going on the appserver (or even on a client) I use a simple tool. - 1) Scan the SESSION on the Appserver and collect objects that stay in memory. Pass the data as a temp-table to the client. - 2) Do something like calling your sample.p on the appserver - 3) again 1) Normally the result of 1) and 3) should show the same objects. If the object list grows then you may have a problem. /* MemoryChecker.i/ DEFINE TEMP-TABLE ttDynObject NO-UNDO FIELD ObjectNumber AS INTEGER LABEL "Number" FIELD ObjectHandle AS HANDLE LABEL "Handle" FIELD ObjectType AS CHARACTER FORMAT "x(32)" LABEL "Type" FIELD ObjectName AS CHARACTER FORMAT "x(80)" LABEL "Name" INDEX pix IS PRIMARY UNIQUE ObjectNumber. /* MemoryChecker.p */ {MemoryChecker.i} DEFINE OUTPUT PARAMETER TABLE FOR ttDynObject. DEFINE VARIABLE hObject AS HANDLE NO-UNDO. DEFINE VARIABLE oObject AS Progress.Lang.Object NO-UNDO. DEFINE VARIABLE iSeq AS INTEGER NO-UNDO. hObject = SESSION:FIRST-PROCEDURE. RUN addWidgets(hObject). hObject = SESSION:FIRST-DATASET. RUN addWidgets(hObject). hObject = SESSION:FIRST-BUFFER. RUN addWidgets(hObject). hObject = SESSION:FIRST-QUERY. RUN addWidgets(hObject). hObject = SESSION:FIRST-DATA-SOURCE. RUN addWidgets(hObject). hObject = SESSION:FIRST-CHILD. RUN addWidgets(hObject). /* hObject = SESSION:FIRST-SERVER. RUN addWidgets(hObject). */ oObject = SESSION:FIRST-OBJECT. DO WHILE VALID-OBJECT(oObject): CREATE ttDynObject. ASSIGN iSeq = iSeq + 1 ttDynObject.ObjectNumber = iSeq ttDynObject.ObjectType = oObject:GetClass():TypeName ttDynObject.ObjectName = oObject:ToString() oObject = oObject:NEXT-SIBLING. END. PROCEDURE addWidgets: DEFINE INPUT PARAMETER phObject AS HANDLE NO-UNDO. DO WHILE VALID-HANDLE(hObject): CREATE ttDynObject. ASSIGN iSeq = iSeq + 1 ttDynObject.ObjectNumber = iSeq ttDynObject.ObjectHandle = hObject ttDynObject.ObjectType = hObject:TYPE ttDynObject.ObjectName = hObject:NAME. hObject = hObject:NEXT-SIBLING. END. END. /* Client prog */ {MemoryChecker.i} RUN MemoryChecker.p ON SERVER (OUTPUT TABLE ttDynObject). Then you can load the temp-table into a browse or better a .Net grid with grouping. If you display the number of records of ttDynObject it's easy to see if something goes wrong. All of this only makes sense if the client talks to the same appserver agent for every request. - Start the appserver with a single agent (in development). - Make the appserver agent stateless bound for the time of checking. (Start a .p o the appserver persistent and delete it when you are done). Good luck... Thomas

Continue reading...
 
Status
Not open for further replies.
Top