1 /* Copyright (C) 2021 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
22 #include "DbeSession.h"
24 #include "StringBuilder.h"
27 #include "HeapActivity.h"
28 #include "MetricList.h"
29 #include "Application.h"
30 #include "Experiment.h"
32 #include "Exp_Layout.h"
35 HeapActivity::HeapActivity (DbeView *_dbev)
40 hDataObjsCallStack = NULL;
42 hDataCalStkMap = NULL;
43 hist_data_callstack_all = NULL;
47 HeapActivity::reset ()
51 delete hDataObjsCallStack;
52 hDataObjsCallStack = NULL;
55 delete hDataCalStkMap;
56 hDataCalStkMap = NULL;
57 hist_data_callstack_all = NULL;
61 HeapActivity::createHistItemTotals (Hist_data *hist_data, MetricList *mlist,
62 Histable::Type hType, bool empty)
66 Hist_data::HistItem *hi;
67 HeapData *hData = NULL;
68 if (hDataTotal == NULL)
70 hDataTotal = new HeapData (TOTAL_HEAPNAME);
71 hDataTotal->setHistType (hType);
72 hDataTotal->setStackId (TOTAL_STACK_ID);
76 hData = new HeapData (hDataTotal);
77 hData->setHistType (hType);
78 hi = hist_data->append_hist_item (hData);
80 Vec_loop (Metric *, mlist->get_items (), mIndex, mtr)
82 if (!mtr->is_visible () && !mtr->is_tvisible () && !mtr->is_pvisible ())
85 Metric::Type mtype = mtr->get_type ();
86 ValueTag vType = mtr->get_vtype ();
88 hist_data->total->value[mIndex].tag = vType;
89 hi->value[mIndex].tag = vType;
92 case BaseMetric::HEAP_ALLOC_BYTES:
95 hist_data->total->value[mIndex].ll = hDataTotal->getAllocBytes ();
96 hi->value[mIndex].ll = hDataTotal->getAllocBytes ();
100 hist_data->total->value[mIndex].ll = 0;
101 hi->value[mIndex].ll = 0;
104 case BaseMetric::HEAP_ALLOC_CNT:
107 hist_data->total->value[mIndex].ll = hDataTotal->getAllocCnt ();
108 hi->value[mIndex].ll = hDataTotal->getAllocCnt ();
112 hist_data->total->value[mIndex].ll = 0;
113 hi->value[mIndex].ll = 0;
116 case BaseMetric::HEAP_LEAK_BYTES:
119 hist_data->total->value[mIndex].ll = hDataTotal->getLeakBytes ();
120 hi->value[mIndex].ll = hDataTotal->getLeakBytes ();
124 hist_data->total->value[mIndex].ll = 0;
125 hi->value[mIndex].ll = 0;
128 case BaseMetric::HEAP_LEAK_CNT:
131 hist_data->total->value[mIndex].ll = hDataTotal->getLeakCnt ();
132 hi->value[mIndex].ll = hDataTotal->getLeakCnt ();
136 hist_data->total->value[mIndex].ll = 0;
137 hi->value[mIndex].ll = 0;
147 HeapActivity::computeHistTotals (Hist_data *hist_data, MetricList *mlist)
151 Vec_loop (Metric *, mlist->get_items (), mIndex, mtr)
153 if (!mtr->is_visible () && !mtr->is_tvisible () && !mtr->is_pvisible ())
156 Metric::Type mtype = mtr->get_type ();
157 ValueTag vType = mtr->get_vtype ();
159 hist_data->total->value[mIndex].tag = vType;
162 case BaseMetric::HEAP_ALLOC_BYTES:
163 hist_data->total->value[mIndex].ll = hDataTotal->getAllocBytes ();
165 case BaseMetric::HEAP_ALLOC_CNT:
166 hist_data->total->value[mIndex].ll = hDataTotal->getAllocCnt ();
168 case BaseMetric::HEAP_LEAK_BYTES:
169 hist_data->total->value[mIndex].ll = hDataTotal->getLeakBytes ();
171 case BaseMetric::HEAP_LEAK_CNT:
172 hist_data->total->value[mIndex].ll = hDataTotal->getLeakCnt ();
181 HeapActivity::computeHistData (Hist_data *hist_data, MetricList *mlist,
182 Hist_data::Mode mode, Histable *selObj)
185 Hist_data::HistItem *hi = NULL;
187 int numObjs = hDataObjs->size ();
188 int numMetrics = mlist->get_items ()->size ();
189 for (int i = 0; i < numObjs; i++)
191 HeapData *hData = hDataObjs->fetch (i);
192 if (mode == Hist_data::ALL)
193 hi = hist_data->append_hist_item (hData);
194 else if (mode == Hist_data::SELF)
196 if (hData->id == selObj->id)
197 hi = hist_data->append_hist_item (hData);
202 for (int mIndex = 0; mIndex < numMetrics; mIndex++)
204 Metric *mtr = mlist->get_items ()->fetch (mIndex);
205 if (!mtr->is_visible () && !mtr->is_tvisible ()
206 && !mtr->is_pvisible ())
209 Metric::Type mtype = mtr->get_type ();
210 ValueTag vType = mtr->get_vtype ();
211 hi->value[mIndex].tag = vType;
214 case BaseMetric::HEAP_ALLOC_BYTES:
215 hi->value[mIndex].ll = hData->getAllocBytes ();
217 case BaseMetric::HEAP_ALLOC_CNT:
218 hi->value[mIndex].ll = hData->getAllocCnt ();
220 case BaseMetric::HEAP_LEAK_BYTES:
221 hi->value[mIndex].ll = hData->getLeakBytes ();
223 case BaseMetric::HEAP_LEAK_CNT:
224 hi->value[mIndex].ll = hData->getLeakCnt ();
234 HeapActivity::compute_metrics (MetricList *mlist, Histable::Type type,
235 Hist_data::Mode mode, Histable *selObj)
237 // it's already there, just return it
238 if (mode == Hist_data::ALL && type == Histable::HEAPCALLSTACK
239 && hist_data_callstack_all != NULL)
240 return hist_data_callstack_all;
242 bool has_data = false;
243 Hist_data *hist_data = NULL;
244 VMode viewMode = dbev->get_view_mode ();
247 case Histable::HEAPCALLSTACK:
248 if (!hasCallStack) // It is not computed yet
249 computeCallStack (type, viewMode);
251 // computeCallStack() creates hDataObjsCallStack
252 // hDataObjsCallStack contains the list of call stack objects
253 if (hDataObjsCallStack != NULL)
255 hDataObjs = hDataObjsCallStack;
261 if (has_data && mode == Hist_data::ALL && hist_data_callstack_all == NULL)
263 hist_data_callstack_all = new Hist_data (mlist, type, mode, true);
264 hist_data = hist_data_callstack_all;
267 hist_data = new Hist_data (mlist, type, mode, false);
270 hist_data = new Hist_data (mlist, type, mode, false);
271 createHistItemTotals (hist_data, mlist, type, true);
277 "HeapActivity cannot process data due to wrong Histable (type=%d) \n",
282 if (mode == Hist_data::ALL || (mode == Hist_data::SELF && selObj->id == 0))
283 createHistItemTotals (hist_data, mlist, type, false);
285 computeHistTotals (hist_data, mlist);
286 computeHistData (hist_data, mlist, mode, selObj);
288 // Determine by which metric to sort if any
289 bool rev_sort = mlist->get_sort_rev ();
291 int nmetrics = mlist->get_items ()->size ();
293 for (int mind = 0; mind < nmetrics; mind++)
294 if (mlist->get_sort_ref_index () == mind)
297 hist_data->sort (sort_ind, rev_sort);
298 hist_data->compute_minmax ();
304 HeapActivity::computeCallStack (Histable::Type type, VMode viewMode)
306 bool has_data = false;
308 uint64_t stackIndex = 0;
309 HeapData *hData = NULL;
311 delete hDataCalStkMap;
312 hDataCalStkMap = new DefaultMap<uint64_t, HeapData*>;
315 hDataTotal = new HeapData (TOTAL_HEAPNAME);
316 hDataTotal->setHistType (type);
318 // There is no call stack for total, use the index for id
319 hDataTotal->id = stackIndex++;
321 // get the list of io events from DbeView
322 int numExps = dbeSession->nexps ();
324 for (int k = 0; k < numExps; k++)
326 // Investigate the performance impact of processing the heap events twice.
327 // This is a 2*n performance issue
328 dbev->get_filtered_events (k, DATA_HEAPSZ);
330 DataView *heapPkts = dbev->get_filtered_events (k, DATA_HEAP);
331 if (heapPkts == NULL)
334 Experiment *exp = dbeSession->get_exp (k);
335 long sz = heapPkts->getSize ();
340 pid = exp->getPID ();
341 userExpId = exp->getUserExpId ();
343 for (long i = 0; i < sz; ++i)
345 uint64_t nByte = heapPkts->getULongValue (PROP_HSIZE, i);
346 uint64_t stackId = (uint64_t) getStack (viewMode, heapPkts, i);
347 Heap_type heapType = (Heap_type) heapPkts->getIntValue (PROP_HTYPE, i);
348 uint64_t leaked = heapPkts->getULongValue (PROP_HLEAKED, i);
349 int64_t heapSize = heapPkts->getLongValue (PROP_HCUR_ALLOCS, i);
350 hrtime_t packetTimestamp = heapPkts->getLongValue (PROP_TSTAMP, i);
351 hrtime_t timestamp = packetTimestamp - exp->getStartTime () +
352 exp->getRelativeStartTime ();
361 hData = hDataCalStkMap->get (stackId);
364 char *stkName = dbe_sprintf (GTXT ("Stack 0x%llx"),
365 (unsigned long long) stackId);
366 hData = new HeapData (stkName);
367 hDataCalStkMap->put (stackId, hData);
368 hData->id = (int64_t) stackId;
369 hData->setStackId (stackIndex);
371 hData->setHistType (type);
377 hData->addAllocEvent (nByte);
378 hDataTotal->addAllocEvent (nByte);
379 hDataTotal->setAllocStat (nByte);
380 hDataTotal->setPeakMemUsage (heapSize, hData->getStackId (),
381 timestamp, pid, userExpId);
384 hData->addLeakEvent (leaked);
385 hDataTotal->addLeakEvent (leaked);
386 hDataTotal->setLeakStat (leaked);
392 hData = new HeapData (TOTAL_HEAPNAME);
393 hDataTotal->setPeakMemUsage (heapSize, hData->getStackId (),
394 timestamp, pid, userExpId);
405 hDataObjsCallStack = hDataCalStkMap->values ()->copy ();