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 "IOActivity.h"
28 #include "MetricList.h"
29 #include "Application.h"
30 #include "Experiment.h"
32 #include "Exp_Layout.h"
35 IOActivity::IOActivity (DbeView *_dbev)
45 fDataObjsCallStack = NULL;
47 fDataCalStkMap = NULL;
49 hist_data_file_all = NULL;
50 hist_data_vfd_all = NULL;
51 hist_data_callstack_all = NULL;
57 int numExps = dbeSession->nexps ();
58 FileData *fData = NULL;
59 DefaultMap<int64_t, FileData*>* fDataMap;
60 for (int k = 0; k < numExps; k++)
62 Experiment *exp = dbeSession->get_exp (k);
63 fDataMap = exp->getFDataMap ();
67 fDataObjs = fDataMap->values ();
68 if (fDataObjs == NULL)
70 int numFiles = fDataObjs->size ();
71 for (int j = 0; j < numFiles; j++)
73 fData = fDataObjs->fetch (j);
91 delete fDataObjsCallStack;
92 fDataObjsCallStack = NULL;
97 delete fDataCalStkMap;
98 fDataCalStkMap = NULL;
102 // These three pointers are deleted by DbeView
103 // They are named iofile_data, iovfd_data, and iocs_data
104 hist_data_file_all = NULL;
105 hist_data_vfd_all = NULL;
106 hist_data_callstack_all = NULL;
110 IOActivity::createHistItemTotals (Hist_data *hist_data, MetricList *mlist,
111 Histable::Type hType, bool empty)
115 Hist_data::HistItem *hi;
116 FileData *fData = NULL;
118 if (fDataTotal == NULL)
120 fDataTotal = new FileData (TOTAL_FILENAME);
121 fDataTotal->setHistType (hType);
122 fDataTotal->setVirtualFd (VIRTUAL_FD_TOTAL);
126 fData = new FileData (fDataTotal);
127 fData->setHistType (hType);
128 hi = hist_data->append_hist_item (fData);
129 Vec_loop (Metric *, mlist->get_items (), mIndex, mtr)
131 if (!mtr->is_visible () && !mtr->is_tvisible () && !mtr->is_pvisible ())
134 Metric::Type mtype = mtr->get_type ();
135 ValueTag vType = mtr->get_vtype ();
136 hist_data->total->value[mIndex].tag = vType;
137 hi->value[mIndex].tag = vType;
138 double prec = (double) NANOSEC;
141 case BaseMetric::IO_READ_BYTES:
144 hist_data->total->value[mIndex].ll = fDataTotal->getReadBytes ();
145 hi->value[mIndex].ll = fDataTotal->getReadBytes ();
149 hist_data->total->value[mIndex].ll = 0;
150 hi->value[mIndex].ll = 0;
153 case BaseMetric::IO_READ_CNT:
156 hist_data->total->value[mIndex].ll = fDataTotal->getReadCnt ();
157 hi->value[mIndex].ll = fDataTotal->getReadCnt ();
161 hist_data->total->value[mIndex].ll = 0;
162 hi->value[mIndex].ll = 0;
165 case BaseMetric::IO_READ_TIME:
168 hist_data->total->value[mIndex].d =
169 (double) fDataTotal->getReadTime () / prec;
170 hi->value[mIndex].d = hist_data->total->value[mIndex].d;
174 hist_data->total->value[mIndex].d = 0.0;
175 hi->value[mIndex].d = 0.0;
178 case BaseMetric::IO_WRITE_BYTES:
181 hist_data->total->value[mIndex].ll = fDataTotal->getWriteBytes ();
182 hi->value[mIndex].ll = fDataTotal->getWriteBytes ();
186 hist_data->total->value[mIndex].ll = 0;
187 hi->value[mIndex].ll = 0;
190 case BaseMetric::IO_WRITE_CNT:
193 hist_data->total->value[mIndex].ll = fDataTotal->getWriteCnt ();
194 hi->value[mIndex].ll = fDataTotal->getWriteCnt ();
198 hist_data->total->value[mIndex].ll = 0;
199 hi->value[mIndex].ll = 0;
202 case BaseMetric::IO_WRITE_TIME:
205 hist_data->total->value[mIndex].d =
206 (double) fDataTotal->getWriteTime () / prec;
207 hi->value[mIndex].d = hist_data->total->value[mIndex].d;
211 hist_data->total->value[mIndex].d = 0.0;
212 hi->value[mIndex].d = 0.0;
215 case BaseMetric::IO_OTHER_CNT:
218 hist_data->total->value[mIndex].ll = fDataTotal->getOtherCnt ();
219 hi->value[mIndex].ll = fDataTotal->getOtherCnt ();
223 hist_data->total->value[mIndex].ll = 0;
224 hi->value[mIndex].ll = 0;
227 case BaseMetric::IO_OTHER_TIME:
230 hist_data->total->value[mIndex].d =
231 (double) fDataTotal->getOtherTime () / prec;
232 hi->value[mIndex].d = hist_data->total->value[mIndex].d;
236 hist_data->total->value[mIndex].d = 0.0;
237 hi->value[mIndex].d = 0.0;
240 case BaseMetric::IO_ERROR_CNT:
243 hist_data->total->value[mIndex].ll = fDataTotal->getErrorCnt ();
244 hi->value[mIndex].ll = fDataTotal->getErrorCnt ();
248 hist_data->total->value[mIndex].ll = 0;
249 hi->value[mIndex].ll = 0;
252 case BaseMetric::IO_ERROR_TIME:
255 hist_data->total->value[mIndex].d = (double) fDataTotal->getErrorTime () / prec;
256 hi->value[mIndex].d = hist_data->total->value[mIndex].d;
260 hist_data->total->value[mIndex].d = 0.0;
261 hi->value[mIndex].d = 0.0;
271 IOActivity::computeHistTotals (Hist_data *hist_data, MetricList *mlist)
275 Vec_loop (Metric *, mlist->get_items (), mIndex, mtr)
277 if (!mtr->is_visible () && !mtr->is_tvisible () && !mtr->is_pvisible ())
280 Metric::Type mtype = mtr->get_type ();
281 ValueTag vType = mtr->get_vtype ();
282 hist_data->total->value[mIndex].tag = vType;
283 double prec = (double) NANOSEC;
286 case BaseMetric::IO_READ_BYTES:
287 hist_data->total->value[mIndex].ll = fDataTotal->getReadBytes ();
289 case BaseMetric::IO_READ_CNT:
290 hist_data->total->value[mIndex].ll = fDataTotal->getReadCnt ();
292 case BaseMetric::IO_READ_TIME:
293 hist_data->total->value[mIndex].d =
294 (double) fDataTotal->getReadTime () / prec;
296 case BaseMetric::IO_WRITE_BYTES:
297 hist_data->total->value[mIndex].ll = fDataTotal->getWriteBytes ();
299 case BaseMetric::IO_WRITE_CNT:
300 hist_data->total->value[mIndex].ll = fDataTotal->getWriteCnt ();
302 case BaseMetric::IO_WRITE_TIME:
303 hist_data->total->value[mIndex].d =
304 (double) fDataTotal->getWriteTime () / prec;
306 case BaseMetric::IO_OTHER_CNT:
307 hist_data->total->value[mIndex].ll = fDataTotal->getOtherCnt ();
309 case BaseMetric::IO_OTHER_TIME:
310 hist_data->total->value[mIndex].d =
311 (double) fDataTotal->getOtherTime () / prec;
313 case BaseMetric::IO_ERROR_CNT:
314 hist_data->total->value[mIndex].ll = fDataTotal->getErrorCnt ();
316 case BaseMetric::IO_ERROR_TIME:
317 hist_data->total->value[mIndex].d =
318 (double) fDataTotal->getErrorTime () / prec;
327 IOActivity::computeHistData (Hist_data *hist_data, MetricList *mlist,
328 Hist_data::Mode mode, Histable *selObj)
331 Hist_data::HistItem *hi = NULL;
332 int numObjs = fDataObjs->size ();
333 int numMetrics = mlist->get_items ()->size ();
335 for (int i = 0; i < numObjs; i++)
337 FileData *fData = fDataObjs->fetch (i);
338 if (mode == Hist_data::ALL)
339 hi = hist_data->append_hist_item (fData);
340 else if (mode == Hist_data::SELF)
342 if (fData->id == selObj->id)
343 hi = hist_data->append_hist_item (fData);
348 for (int mIndex = 0; mIndex < numMetrics; mIndex++)
350 Metric *mtr = mlist->get_items ()->fetch (mIndex);
351 if (!mtr->is_visible () && !mtr->is_tvisible ()
352 && !mtr->is_pvisible ())
355 Metric::Type mtype = mtr->get_type ();
356 ValueTag vType = mtr->get_vtype ();
357 hi->value[mIndex].tag = vType;
359 double prec = (double) NANOSEC;
362 case BaseMetric::IO_READ_BYTES:
363 hi->value[mIndex].ll = fData->getReadBytes ();
365 case BaseMetric::IO_READ_CNT:
366 hi->value[mIndex].ll = fData->getReadCnt ();
368 case BaseMetric::IO_READ_TIME:
369 hi->value[mIndex].d = (double) fData->getReadTime () / prec;
371 case BaseMetric::IO_WRITE_BYTES:
372 hi->value[mIndex].ll = fData->getWriteBytes ();
374 case BaseMetric::IO_WRITE_CNT:
375 hi->value[mIndex].ll = fData->getWriteCnt ();
377 case BaseMetric::IO_WRITE_TIME:
378 hi->value[mIndex].d = (double) fData->getWriteTime () / prec;
380 case BaseMetric::IO_OTHER_CNT:
381 hi->value[mIndex].ll = fData->getOtherCnt ();
383 case BaseMetric::IO_OTHER_TIME:
384 hi->value[mIndex].d = (double) fData->getOtherTime () / prec;
386 case BaseMetric::IO_ERROR_CNT:
387 hi->value[mIndex].ll = fData->getErrorCnt ();
389 case BaseMetric::IO_ERROR_TIME:
390 hi->value[mIndex].d = (double) fData->getErrorTime () / prec;
400 IOActivity::compute_metrics (MetricList *mlist, Histable::Type type,
401 Hist_data::Mode mode, Histable *selObj)
404 // it's already there, just return it
405 if (mode == Hist_data::ALL)
407 if (type == Histable::IOACTFILE && hist_data_file_all)
408 return hist_data_file_all;
409 else if (type == Histable::IOACTVFD && hist_data_vfd_all)
410 return hist_data_vfd_all;
411 else if (type == Histable::IOCALLSTACK && hist_data_callstack_all)
412 return hist_data_callstack_all;
415 bool has_data = false;
416 Hist_data *hist_data = NULL;
417 VMode viewMode = dbev->get_view_mode ();
421 case Histable::IOACTVFD:
425 // computeData() creates fDataObjsVfd
426 // fDataObjsVfd contains the list of vfd objects
427 if (fDataObjsVfd != NULL)
429 // fDataObjs is used in other methods
430 fDataObjs = fDataObjsVfd;
436 if (has_data && mode == Hist_data::ALL && hist_data_vfd_all == NULL)
438 hist_data_vfd_all = new Hist_data (mlist, type, mode, true);
439 hist_data = hist_data_vfd_all;
442 hist_data = new Hist_data (mlist, type, mode, false);
445 hist_data = new Hist_data (mlist, type, mode, false);
446 createHistItemTotals (hist_data, mlist, type, true);
450 case Histable::IOACTFILE:
454 // computeData() creates fDataObjsFile
455 // fDataObjsFile contains the list of file objects
456 if (fDataObjsFile != NULL)
458 fDataObjs = fDataObjsFile;
464 if (has_data && mode == Hist_data::ALL && hist_data_file_all == NULL)
466 hist_data_file_all = new Hist_data (mlist, type, mode, true);
467 hist_data = hist_data_file_all;
470 hist_data = new Hist_data (mlist, type, mode, false);
473 hist_data = new Hist_data (mlist, type, mode, false);
474 createHistItemTotals (hist_data, mlist, type, true);
478 case Histable::IOCALLSTACK:
480 computeCallStack (type, viewMode);
482 // computeCallStack() creates fDataObjsCallStack
483 // fDataObjsCallStack contains the list of call stack objects
484 if (fDataObjsCallStack != NULL)
486 fDataObjs = fDataObjsCallStack;
492 if (has_data && (mode == Hist_data::ALL) && (hist_data_callstack_all == NULL))
494 hist_data_callstack_all = new Hist_data (mlist, type, mode, true);
495 hist_data = hist_data_callstack_all;
498 hist_data = new Hist_data (mlist, type, mode, false);
501 hist_data = new Hist_data (mlist, type, mode, false);
502 createHistItemTotals (hist_data, mlist, type, true);
508 "IOActivity cannot process data due to wrong Histable (type=%d) \n",
513 if (mode == Hist_data::ALL || (mode == Hist_data::SELF && selObj->id == 0))
514 createHistItemTotals (hist_data, mlist, type, false);
516 computeHistTotals (hist_data, mlist);
517 computeHistData (hist_data, mlist, mode, selObj);
519 // Determine by which metric to sort if any
520 bool rev_sort = mlist->get_sort_rev ();
522 int nmetrics = mlist->get_items ()->size ();
523 for (int mind = 0; mind < nmetrics; mind++)
524 if (mlist->get_sort_ref_index () == mind)
527 hist_data->sort (sort_ind, rev_sort);
528 hist_data->compute_minmax ();
533 IOActivity::computeData (Histable::Type type)
535 bool has_iodata = false;
537 int64_t histableId = 0; // It is used by fDataAggr only
538 // fData uses vfd for histable id
540 fDataHash = new HashMap<char*, FileData*>;
541 FileData *fData = NULL;
542 FileData *fDataAggr = NULL;
544 fDataTotal = new FileData (TOTAL_FILENAME);
545 fDataTotal->setHistType (type);
546 fDataTotal->setVirtualFd (VIRTUAL_FD_TOTAL);
547 fDataTotal->id = histableId++;
549 FileData *fDataStdin = new FileData (STDIN_FILENAME);
550 fDataStdin->setFileDes (STDIN_FD);
551 fDataStdin->setHistType (type);
552 fDataStdin->setFsType ("N/A");
553 fDataStdin->id = histableId++;
555 FileData *fDataStdout = new FileData (STDOUT_FILENAME);
556 fDataStdout->setFileDes (STDOUT_FD);
557 fDataStdout->setHistType (type);
558 fDataStdout->setFsType ("N/A");
559 fDataStdout->id = histableId++;
561 FileData *fDataStderr = new FileData (STDERR_FILENAME);
562 fDataStderr->setFileDes (STDERR_FD);
563 fDataStderr->setHistType (type);
564 fDataStderr->setFsType ("N/A");
565 fDataStderr->id = histableId++;
567 FileData *fDataOtherIO = new FileData (OTHERIO_FILENAME);
568 fDataOtherIO->setFileDes (OTHERIO_FD);
569 fDataOtherIO->setHistType (type);
570 fDataOtherIO->setFsType ("N/A");
571 fDataOtherIO->id = histableId++;
573 DefaultMap<int64_t, FileData*>* fDataMap;
574 fDataObjsFile = NULL;
577 // get the list of io events from DbeView
578 int numExps = dbeSession->nexps ();
580 for (int k = 0; k < numExps; k++)
582 DataView *ioPkts = dbev->get_filtered_events (k, DATA_IOTRACE);
583 if (ioPkts == NULL || ioPkts->getSize () <= 0)
585 Experiment *exp = dbeSession->get_exp (k);
586 fDataMap = exp->getFDataMap ();
587 if (fDataMap == NULL)
590 fDataVfdMap = new DefaultMap<long, FileData*>;
592 long sz = ioPkts->getSize ();
593 for (long i = 0; i < sz; ++i)
595 hrtime_t event_duration = ioPkts->getLongValue (PROP_EVT_TIME, i);
596 int64_t nByte = ioPkts->getLongValue (PROP_IONBYTE, i);
597 IOTrace_type ioType = (IOTrace_type) ioPkts->getIntValue (PROP_IOTYPE, i);
598 int64_t vFd = ioPkts->getLongValue (PROP_IOVFD, i);
601 fData = fDataMap->get (vFd);
608 if (fDataVfdMap->get (vFd) == NULL)
609 fDataVfdMap->put (vFd, fData);
614 fData->addReadEvent (event_duration, nByte);
615 // Set the Histable id for IOVFD
616 fData->id = fData->getVirtualFd ();
617 fDataTotal->addReadEvent (event_duration, nByte);
618 fDataTotal->setReadStat (event_duration, nByte);
621 fData->addWriteEvent (event_duration, nByte);
622 // Set the Histable id for IOVFD
623 fData->id = fData->getVirtualFd ();
624 fDataTotal->addWriteEvent (event_duration, nByte);
625 fDataTotal->setWriteStat (event_duration, nByte);
628 fData->addOtherEvent (event_duration);
629 // Set the Histable id for IOVFD
630 fData->id = fData->getVirtualFd ();
631 fDataTotal->addOtherEvent (event_duration);
635 fData->addOtherEvent (event_duration);
636 // Set the Histable id for IOVFD
637 fData->id = fData->getVirtualFd ();
638 fDataTotal->addOtherEvent (event_duration);
640 case READ_TRACE_ERROR:
641 case WRITE_TRACE_ERROR:
642 case OPEN_TRACE_ERROR:
643 case CLOSE_TRACE_ERROR:
644 case OTHERIO_TRACE_ERROR:
645 fData->addErrorEvent (event_duration);
646 // Set the Histable id for IOVFD
647 fData->id = fData->getVirtualFd ();
648 fDataTotal->addErrorEvent (event_duration);
651 case IOTRACETYPE_LAST:
655 if (type == Histable::IOACTFILE)
657 fDataAggr = fDataHash->get (fData->getFileName ());
658 if (fDataAggr == NULL)
660 bool setInfo = false;
661 if (vFd == VIRTUAL_FD_STDIN)
662 fDataAggr = fDataStdin;
663 else if (vFd == VIRTUAL_FD_STDOUT)
664 fDataAggr = fDataStdout;
665 else if (vFd == VIRTUAL_FD_STDERR)
666 fDataAggr = fDataStderr;
667 else if (vFd == VIRTUAL_FD_OTHERIO)
668 fDataAggr = fDataOtherIO;
671 fDataAggr = new FileData (fData->getFileName ());
674 fDataHash->put (fData->getFileName (), fDataAggr);
678 fDataAggr->setFsType (fData->getFsType ());
679 fDataAggr->setHistType (type);
680 // Set the Histable id for aggregated file name
681 fDataAggr->id = histableId;
682 fDataAggr->setVirtualFd (histableId);
687 fDataAggr->setFileDesList (fData->getFileDes ());
688 fDataAggr->setVirtualFds (fData->getVirtualFd ());
692 fDataAggr->addReadEvent (event_duration, nByte);
695 fDataAggr->addWriteEvent (event_duration, nByte);
698 fDataAggr->addOtherEvent (event_duration);
702 fDataAggr->addOtherEvent (event_duration);
704 case READ_TRACE_ERROR:
705 case WRITE_TRACE_ERROR:
706 case OPEN_TRACE_ERROR:
707 case CLOSE_TRACE_ERROR:
708 case OTHERIO_TRACE_ERROR:
709 fDataAggr->addErrorEvent (event_duration);
711 case IOTRACETYPE_LAST:
719 if (fDataObjsVfd == NULL)
720 fDataObjsVfd = new Vector<FileData*>;
721 fDataObjsVfd->addAll (fDataVfdMap->values ());
725 if (has_iodata && type == Histable::IOACTFILE)
727 fDataObjsFile = fDataHash->values ()->copy ();
733 IOActivity::computeCallStack (Histable::Type type, VMode viewMode)
735 bool has_data = false;
736 int64_t stackIndex = 0;
737 FileData *fData = NULL;
738 delete fDataCalStkMap;
739 fDataCalStkMap = new DefaultMap<void*, FileData*>;
741 fDataTotal = new FileData (TOTAL_FILENAME);
742 fDataTotal->setHistType (type);
744 // There is no call stack for total, use the index for id
745 fDataTotal->id = stackIndex++;
747 // get the list of io events from DbeView
748 int numExps = dbeSession->nexps ();
749 for (int k = 0; k < numExps; k++)
751 DataView *ioPkts = dbev->get_filtered_events (k, DATA_IOTRACE);
752 if (ioPkts == NULL || ioPkts->getSize () <= 0)
754 long sz = ioPkts->getSize ();
755 for (long i = 0; i < sz; ++i)
757 hrtime_t event_duration = ioPkts->getLongValue (PROP_EVT_TIME, i);
758 int64_t nByte = ioPkts->getLongValue (PROP_IONBYTE, i);
759 void *stackId = getStack (viewMode, ioPkts, i);
760 IOTrace_type ioType =
761 (IOTrace_type) ioPkts->getIntValue (PROP_IOTYPE, i);
762 int64_t vFd = ioPkts->getLongValue (PROP_IOVFD, i);
764 if (stackId != NULL && vFd > 0)
766 fData = fDataCalStkMap->get (stackId);
769 char *stkName = dbe_sprintf (GTXT ("Stack 0x%llx"),
770 (unsigned long long) stackId);
771 fData = new FileData (stkName);
772 fDataCalStkMap->put (stackId, fData);
773 fData->id = (int64_t) stackId;
774 fData->setVirtualFd (stackIndex);
776 fData->setHistType (type);
785 fData->addReadEvent (event_duration, nByte);
786 fDataTotal->addReadEvent (event_duration, nByte);
787 fDataTotal->setReadStat (event_duration, nByte);
790 fData->addWriteEvent (event_duration, nByte);
791 fDataTotal->addWriteEvent (event_duration, nByte);
792 fDataTotal->setWriteStat (event_duration, nByte);
795 fData->addOtherEvent (event_duration);
796 fDataTotal->addOtherEvent (event_duration);
800 fData->addOtherEvent (event_duration);
801 fDataTotal->addOtherEvent (event_duration);
803 case READ_TRACE_ERROR:
804 case WRITE_TRACE_ERROR:
805 case OPEN_TRACE_ERROR:
806 fData->addErrorEvent (event_duration);
807 fDataTotal->addErrorEvent (event_duration);
809 case CLOSE_TRACE_ERROR:
810 case OTHERIO_TRACE_ERROR:
811 fData->addErrorEvent (event_duration);
812 fDataTotal->addErrorEvent (event_duration);
814 case IOTRACETYPE_LAST:
822 fDataObjsCallStack = fDataCalStkMap->values ()->copy ();