File indexing completed on 2024-05-19 05:44:22
0001 /* 0002 SPDX-FileCopyrightText: 2016-2019 Milian Wolff <mail@milianw.de> 0003 0004 SPDX-License-Identifier: LGPL-2.1-or-later 0005 */ 0006 0007 #include "callercalleemodel.h" 0008 0009 #include <KLocalizedString> 0010 0011 CallerCalleeModel::CallerCalleeModel(QObject* parent) 0012 : HashModel(parent) 0013 { 0014 qRegisterMetaType<CallerCalleeResults>(); 0015 } 0016 0017 CallerCalleeModel::~CallerCalleeModel() = default; 0018 0019 void CallerCalleeModel::setResults(const CallerCalleeResults& results) 0020 { 0021 Q_ASSERT(results.resultData); 0022 m_results = results; 0023 setRows(results.entries); 0024 } 0025 0026 void CallerCalleeModel::clearData() 0027 { 0028 m_results = {}; 0029 setRows({}); 0030 } 0031 0032 QVariant CallerCalleeModel::headerCell(int column, int role) const 0033 { 0034 if (role == Qt::InitialSortOrderRole) { 0035 return (column > LocationColumn) ? Qt::DescendingOrder : Qt::AscendingOrder; 0036 } 0037 if (role == Qt::DisplayRole) { 0038 switch (static_cast<Columns>(column)) { 0039 case LocationColumn: 0040 return i18n("Location"); 0041 case SelfAllocationsColumn: 0042 return i18n("Allocations (Self)"); 0043 case SelfTemporaryColumn: 0044 return i18n("Temporary (Self)"); 0045 case SelfPeakColumn: 0046 return i18n("Peak (Self)"); 0047 case SelfLeakedColumn: 0048 return i18n("Leaked (Self)"); 0049 case InclusiveAllocationsColumn: 0050 return i18n("Allocations (Incl.)"); 0051 case InclusiveTemporaryColumn: 0052 return i18n("Temporary (Incl.)"); 0053 case InclusivePeakColumn: 0054 return i18n("Peak (Incl.)"); 0055 case InclusiveLeakedColumn: 0056 return i18n("Leaked (Incl.)"); 0057 case NUM_COLUMNS: 0058 break; 0059 } 0060 } else if (role == Qt::ToolTipRole) { 0061 switch (static_cast<Columns>(column)) { 0062 case LocationColumn: 0063 return i18n("<qt>The parent symbol that called an allocation function. " 0064 "The function name may be unresolved when debug information is missing.</qt>"); 0065 case SelfAllocationsColumn: 0066 return i18n("<qt>The number of times an allocation function was directly " 0067 "called from this location.</qt>"); 0068 case SelfTemporaryColumn: 0069 return i18n("<qt>The number of direct temporary allocations. These " 0070 "allocations are directly followed by a " 0071 "free without any other allocations in-between.</qt>"); 0072 case SelfPeakColumn: 0073 return i18n("<qt>The maximum heap memory in bytes consumed from " 0074 "allocations originating directly at " 0075 "this location. " 0076 "This takes deallocations into account.</qt>"); 0077 case SelfLeakedColumn: 0078 return i18n("<qt>The bytes allocated directly at this location that have " 0079 "not been deallocated.</qt>"); 0080 case InclusiveAllocationsColumn: 0081 return i18n("<qt>The inclusive number of times an allocation function " 0082 "was called from this location or any " 0083 "functions called from here.</qt>"); 0084 case InclusiveTemporaryColumn: 0085 return i18n("<qt>The number of inclusive temporary allocations. These " 0086 "allocations are directly followed by " 0087 "a free without any other allocations in-between.</qt>"); 0088 case InclusivePeakColumn: 0089 return i18n("<qt>The inclusive maximum heap memory in bytes consumed " 0090 "from allocations originating at this " 0091 "location or from functions called from here. " 0092 "This takes deallocations into account.</qt>"); 0093 case InclusiveLeakedColumn: 0094 return i18n("<qt>The bytes allocated at this location that have not been " 0095 "deallocated.</qt>"); 0096 case NUM_COLUMNS: 0097 break; 0098 } 0099 } 0100 return {}; 0101 } 0102 0103 QVariant CallerCalleeModel::cell(int column, int role, const Symbol& symbol, const CallerCalleeEntry& entry) const 0104 { 0105 if (role == SymbolRole) { 0106 return QVariant::fromValue(symbol); 0107 } else if (role == SortRole) { 0108 switch (static_cast<Columns>(column)) { 0109 case LocationColumn: 0110 return Util::toString(symbol, *m_results.resultData, Util::Short); 0111 case SelfAllocationsColumn: 0112 // NOTE: we sort by unsigned absolute value 0113 return QVariant::fromValue<quint64>(std::abs(entry.selfCost.allocations)); 0114 case SelfTemporaryColumn: 0115 return QVariant::fromValue<quint64>(std::abs(entry.selfCost.temporary)); 0116 case SelfPeakColumn: 0117 return QVariant::fromValue<quint64>(std::abs(entry.selfCost.peak)); 0118 case SelfLeakedColumn: 0119 return QVariant::fromValue<quint64>(std::abs(entry.selfCost.leaked)); 0120 case InclusiveAllocationsColumn: 0121 return QVariant::fromValue<quint64>(std::abs(entry.inclusiveCost.allocations)); 0122 case InclusiveTemporaryColumn: 0123 return QVariant::fromValue<quint64>(std::abs(entry.inclusiveCost.temporary)); 0124 case InclusivePeakColumn: 0125 return QVariant::fromValue<quint64>(std::abs(entry.inclusiveCost.peak)); 0126 case InclusiveLeakedColumn: 0127 return QVariant::fromValue<quint64>(std::abs(entry.inclusiveCost.leaked)); 0128 case NUM_COLUMNS: 0129 break; 0130 } 0131 } else if (role == TotalCostRole) { 0132 const auto& totalCosts = m_results.resultData->totalCosts(); 0133 switch (static_cast<Columns>(column)) { 0134 case SelfAllocationsColumn: 0135 case InclusiveAllocationsColumn: 0136 return QVariant::fromValue<qint64>(totalCosts.allocations); 0137 case SelfTemporaryColumn: 0138 case InclusiveTemporaryColumn: 0139 return QVariant::fromValue<qint64>(totalCosts.temporary); 0140 case SelfPeakColumn: 0141 case InclusivePeakColumn: 0142 return QVariant::fromValue<qint64>(totalCosts.peak); 0143 case SelfLeakedColumn: 0144 case InclusiveLeakedColumn: 0145 return QVariant::fromValue<qint64>(totalCosts.leaked); 0146 case LocationColumn: 0147 case NUM_COLUMNS: 0148 break; 0149 } 0150 } else if (role == Qt::DisplayRole) { 0151 switch (static_cast<Columns>(column)) { 0152 case LocationColumn: 0153 return Util::toString(symbol, *m_results.resultData, Util::Short); 0154 case SelfAllocationsColumn: 0155 return QVariant::fromValue<qint64>(entry.selfCost.allocations); 0156 case SelfTemporaryColumn: 0157 return QVariant::fromValue<qint64>(entry.selfCost.temporary); 0158 case SelfPeakColumn: 0159 return Util::formatBytes(entry.selfCost.peak); 0160 case SelfLeakedColumn: 0161 return Util::formatBytes(entry.selfCost.leaked); 0162 case InclusiveAllocationsColumn: 0163 return QVariant::fromValue<qint64>(entry.inclusiveCost.allocations); 0164 case InclusiveTemporaryColumn: 0165 return QVariant::fromValue<qint64>(entry.inclusiveCost.temporary); 0166 case InclusivePeakColumn: 0167 return Util::formatBytes(entry.inclusiveCost.peak); 0168 case InclusiveLeakedColumn: 0169 return Util::formatBytes(entry.inclusiveCost.leaked); 0170 case NUM_COLUMNS: 0171 break; 0172 } 0173 } else if (role == CalleesRole) { 0174 return QVariant::fromValue(entry.callees); 0175 } else if (role == CallersRole) { 0176 return QVariant::fromValue(entry.callers); 0177 } else if (role == SourceMapRole) { 0178 return QVariant::fromValue(entry.sourceMap); 0179 } else if (role == Qt::ToolTipRole) { 0180 return Util::formatTooltip(symbol, entry.selfCost, entry.inclusiveCost, *m_results.resultData); 0181 } else if (role == ResultDataRole) { 0182 return QVariant::fromValue(m_results.resultData.get()); 0183 } 0184 0185 return {}; 0186 } 0187 0188 QModelIndex CallerCalleeModel::indexForSymbol(const Symbol& symbol) const 0189 { 0190 return indexForKey(symbol); 0191 } 0192 0193 CallerModel::CallerModel(QObject* parent) 0194 : SymbolCostModelImpl(parent) 0195 { 0196 } 0197 0198 CallerModel::~CallerModel() = default; 0199 0200 QString CallerModel::symbolHeader() const 0201 { 0202 return i18n("Caller"); 0203 } 0204 0205 CalleeModel::CalleeModel(QObject* parent) 0206 : SymbolCostModelImpl(parent) 0207 { 0208 } 0209 0210 CalleeModel::~CalleeModel() = default; 0211 0212 QString CalleeModel::symbolHeader() const 0213 { 0214 return i18n("Callee"); 0215 } 0216 0217 SourceMapModel::SourceMapModel(QObject* parent) 0218 : LocationCostModelImpl(parent) 0219 { 0220 } 0221 0222 SourceMapModel::~SourceMapModel() = default; 0223 0224 int CallerCalleeModel::numColumns() const 0225 { 0226 return NUM_COLUMNS; 0227 } 0228 0229 #include "moc_callercalleemodel.cpp"