View Full Version : Analyse von Heap memory leaks auf IBM i
Hallo zusammen,
ich muss ein Heap memory Problem auf der AS/400 analysieren. Dazu verwende ich folgende PEX Befehle:
<code>ADDPEXDFN DFN(HEAP) TYPE(*TRACE) JOB((123456/MAT/MAT0 *ALL)) TASK(*ALL) MAXSTG(4000000) TRCTYPE(*SLTEVT) SLTEVT(*YES) MCHINST(*NONE) STGEVT((*ACTGRPHEAP))
</code><code>STRPEX SSNID(HEAP)</code><code>
- Aktion ausführen -
ENDPEX SSNID(HEAP) DTALIB(MATTRC) RPLDTA(*YES)
</code>
Es werden nun ein paar Outfiles erzeugt, die per SQL gejoint werden können, um die Heap-Segment Adresse, die allokierte Größe und den Aufrufstapel zu ermitteln:
<code>CREATE VIEW mattrc/heapv1 AS
(SELECT a.QRECN,
a.QHPASA,
a.QHPASZ,
a.QHPOPR,
a.QHPRET,
(SELECT QPRPNM
FROM mattrc/QAYPEPROCI
WHERE QHPCK1 = QPRKEY) cs1,
QIASTMT1,
(SELECT QPRPNM
FROM mattrc/QAYPEPROCI
WHERE QHPCK2 = QPRKEY) cs2,
QIASTMT2,
(SELECT QPRPNM
FROM mattrc/QAYPEPROCI
WHERE QHPCK3 = QPRKEY) cs3,
QIASTMT3,
(SELECT QPRPNM
FROM mattrc/QAYPEPROCI
WHERE QHPCK4 = QPRKEY) cs4,
QIASTMT4,
(SELECT QPRPNM
FROM mattrc/QAYPEPROCI
WHERE QHPCK5 = QPRKEY) cs5,
QIASTMT5
FROM mattrc/QAYPEHEAP a
INNER JOIN mattrc/QAYPETIDX c
ON a.QRECN = c.QRECN
LEFT JOIN mattrc/QAYPEIAD d
ON a.QRECN = d.QRECN);
</code><code class="sql plain">/* Zeige alle mallocs zu deren Adresse kein </code><code class="sql keyword">free</code> <code class="sql plain">ausgeführt wurde */
</code><code> SELECT *
</code><code> FROM mattrc/heapv1
</code><code> WHERE QHPOPR = 0
</code><code> AND QHPASA NOT IN(SELECT QHPASA FROM mattrc/heapv1
</code><code> WHERE QHPOPR = 1);</code>
Mein Problem ist nun, dass die Datei QAYPEHEAP nur 5 Felder zur Speicherung der letzten 5 Aufrufstapeleinträge enthält. Weiß jemand, wie man mehr Aufrufstapeleinträge erhält?
Wie analysiert ihr Heap memory leak Probleme auf der AS/400?
Auf Windows kann man dazu recht bequem WPA (Windows Performance Analyzer) verwenden.
Viele Grüße
Matthias
Die Frage ist, für welche Sprache?
Im ILERPG habe ich das i.d.R. nicht, da ich keine %alloc benötige. Wichtig ist natürlich vom Code her, alle %alloc auch wieder freizugeben. Da hilft eine reine Speicheranalyse auch eher selten;-).
Es wird ILE C++ verwendet. Da kann es malloc, new .. geben. Mit dem oben genannten PEX Aufruf wird ja bewusst aufgezeichnet, wer Speicher reserviert und auch wieder frei gibt, nur ist halt der Aufrufstapel zu kurz, wodurch dann nicht klar ist, wer die entsprechenden Aufrufer sind.
Ich habe mir der erzeugten Outfile nochmals genauer angeschaut. In Datei QAYPEIAD befindet sich der Callstack immerhin mit bis zu 16 Einträgen, was bei einer C++ Applikation aber immer noch sehr wenig ist.
Die View würde damit so erzeugt werden:
<code class="sql keyword">CREATE</code> <code class="sql color1">or</code> <code class="sql color2">replace</code> <code class="sql keyword">VIEW</code> <code class="sql plain">mattrc/heapv1 </code><code class="sql keyword">AS</code><code class="sql plain">(</code>
<code class="sql keyword">SELECT</code> <code class="sql plain">a.QRECN, a.QHPASA, a.QHPASZ, a.QHPOPR, a.QHPRET,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY16 = QPRKEY) cs16, QIASTMT16,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY15 = QPRKEY) cs15, QIASTMT15,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY14 = QPRKEY) cs14, QIASTMT14,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY13 = QPRKEY) cs13, QIASTMT13,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY12 = QPRKEY) cs12, QIASTMT12,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY11 = QPRKEY) cs11, QIASTMT11,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY10 = QPRKEY) cs10, QIASTMT10,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY9 = QPRKEY) cs9 , QIASTMT9,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY8 = QPRKEY) cs8 , QIASTMT8,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY7 = QPRKEY) cs7 , QIASTMT7,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY6 = QPRKEY) cs6 , QIASTMT6,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY5 = QPRKEY) cs5 , QIASTMT5,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY4 = QPRKEY) cs4 , QIASTMT4,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY3 = QPRKEY) cs3 , QIASTMT3,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY2 = QPRKEY) cs2 , QIASTMT2,</code>
<code class="sql plain">(</code><code class="sql keyword">select</code> <code class="sql plain">rtrim(QPRPGN)||</code><code class="sql string">':'</code><code class="sql plain">||QPRPNM </code><code class="sql keyword">from</code> <code class="sql plain">mattrc/QAYPEPROCI </code><code class="sql keyword">where</code> <code class="sql plain">QIAKEY1 = QPRKEY) cs1 , QIASTMT1</code>
<code class="sql keyword">FROM</code> <code class="sql plain">mattrc/QAYPEHEAP a</code>
<code class="sql color2">LEFT</code> <code class="sql color1">JOIN</code> <code class="sql plain">mattrc/QAYPEIAD b</code>
<code class="sql spaces"> </code><code class="sql keyword">ON</code> <code class="sql plain">a.QRECN = b.QRECN);</code>