File indexing completed on 2024-04-21 05:41:33
0001 /* 0002 This file is part of KCachegrind. 0003 0004 SPDX-FileCopyrightText: 2008-2016 Josef Weidendorfer <Josef.Weidendorfer@gmx.de> 0005 0006 SPDX-License-Identifier: GPL-2.0-only 0007 */ 0008 0009 #include <QCoreApplication> 0010 #include <QTextStream> 0011 0012 #include "tracedata.h" 0013 #include "loader.h" 0014 #include "config.h" 0015 #include "globalconfig.h" 0016 #include "logger.h" 0017 0018 /* 0019 * Just a simple command line tool using libcore 0020 */ 0021 0022 void showHelp(QTextStream& out, bool fullHelp = true) 0023 { 0024 out << "Show profiles from callgrind files. (c) 2010-2016 J. Weidendorfer\n"; 0025 0026 if (!fullHelp) 0027 out << "Type 'cgview -h' for help.\n"; 0028 else 0029 out << "Usage: cgview [options] <file> ...\n\n" 0030 "Options:\n" 0031 " -h Show this help text\n" 0032 " -e Sort list according to exclusive cost\n" 0033 " -s <ev> Sort and show counters for event <ev>\n" 0034 " -c Sort by call count\n" 0035 " -b Show butterfly (callers and callees)\n" 0036 " -n Do not detect recursive cycles\n"; 0037 0038 exit(1); 0039 } 0040 0041 0042 int main(int argc, char** argv) 0043 { 0044 QCoreApplication app(argc, argv); 0045 QTextStream out(stdout); 0046 0047 Loader::initLoaders(); 0048 ConfigStorage::setStorage(new ConfigStorage); 0049 GlobalConfig::config()->addDefaultTypes(); 0050 0051 QStringList list = app.arguments(); 0052 list.pop_front(); 0053 if (list.isEmpty()) showHelp(out, false); 0054 0055 bool sortByExcl = false; 0056 bool sortByCount = false; 0057 bool showCalls = false; 0058 QString showEvent; 0059 QStringList files; 0060 0061 for(int arg = 0; arg<list.count(); arg++) { 0062 if (list[arg] == QLatin1String("-h")) showHelp(out); 0063 else if (list[arg] == QLatin1String("-e")) sortByExcl = true; 0064 else if (list[arg] == QLatin1String("-n")) GlobalConfig::setShowCycles(false); 0065 else if (list[arg] == QLatin1String("-b")) showCalls = true; 0066 else if (list[arg] == QLatin1String("-c")) sortByCount = true; 0067 else if (list[arg] == QLatin1String("-s")) showEvent = list[++arg]; 0068 else 0069 files << list[arg]; 0070 } 0071 TraceData* d = new TraceData(new Logger); 0072 d->load(files); 0073 0074 EventTypeSet* m = d->eventTypes(); 0075 if (m->realCount() == 0) { 0076 out << "Error: No event types found.\n"; 0077 return 1; 0078 } 0079 0080 out << "\nTotals for event types:\n"; 0081 0082 EventType* et; 0083 for (int i=0;i<m->realCount();i++) { 0084 et = m->realType(i); 0085 out.setFieldWidth(14); 0086 out.setFieldAlignment(QTextStream::AlignRight); 0087 out << d->subCost(et).pretty(); 0088 out.setFieldWidth(0); 0089 out << " " << et->longName() << " (" << et->name() << ")\n"; 0090 } 0091 for (int i=0;i<m->derivedCount();i++) { 0092 et = m->derivedType(i); 0093 out.setFieldWidth(14); 0094 out.setFieldAlignment(QTextStream::AlignRight); 0095 out << d->subCost(et).pretty(); 0096 out.setFieldWidth(0); 0097 out << " " << et->longName() << 0098 " (" << et->name() << " = " << et->formula() << ")\n"; 0099 } 0100 out << "\n"; 0101 0102 if (showEvent.isEmpty()) 0103 et = m->realType(0); 0104 else { 0105 et = m->type(showEvent); 0106 if (!et) { 0107 out << "Error: event '" << showEvent << "' not found.\n"; 0108 return 1; 0109 } 0110 } 0111 Q_ASSERT( et!=nullptr ); 0112 out << "Sorted by: " << (sortByExcl ? "Exclusive ":"Inclusive ") 0113 << et->longName() << " (" << et->name() << ")\n"; 0114 0115 QList<TraceFunction*> flist; 0116 HighestCostList hc; 0117 hc.clear(50); 0118 TraceFunctionMap::Iterator it; 0119 for ( it = d->functionMap().begin(); it != d->functionMap().end(); ++it ) 0120 flist.append(&(*it)); 0121 0122 TraceFunction *f; 0123 foreach(f, d->functionCycles()) 0124 flist.append(f); 0125 0126 foreach(f, flist) { 0127 if (sortByCount) 0128 hc.addCost(f, f->calledCount()); 0129 else if (sortByExcl) 0130 hc.addCost(f, f->subCost(et)); 0131 else 0132 hc.addCost(f, f->inclusive()->subCost(et)); 0133 } 0134 0135 0136 out << "\n Inclusive Exclusive Called Function name (DSO)\n"; 0137 out << " ==================================================================\n"; 0138 0139 out.setFieldAlignment(QTextStream::AlignRight); 0140 for(int i=0; i<hc.realCount(); i++) { 0141 f = (TraceFunction*)hc[i]; 0142 0143 if (showCalls) { 0144 if (i>0) out << "\n"; 0145 foreach(TraceCall* c, f->callers()) { 0146 out << " "; 0147 out.setFieldWidth(14); 0148 out << c->subCost(et).pretty(); 0149 out.setFieldWidth(0); 0150 out << " "; 0151 out.setFieldWidth(13); 0152 out << c->prettyCallCount(); 0153 out.setFieldWidth(0); 0154 out << " < " << c->caller()->prettyName() << "\n"; 0155 } 0156 } 0157 0158 out.setFieldWidth(14); 0159 out << f->inclusive()->subCost(et).pretty(); 0160 out << f->subCost(et).pretty(); 0161 out.setFieldWidth(13); 0162 out << f->prettyCalledCount(); 0163 out.setFieldWidth(0); 0164 out << " " << f->name() << " (" << f->object()->name() << ")" << "\n"; 0165 0166 if (showCalls) { 0167 foreach(TraceCall* c, f->callings()) { 0168 out << " "; 0169 out.setFieldWidth(14); 0170 out << c->subCost(et).pretty(); 0171 out.setFieldWidth(0); 0172 out << " "; 0173 out.setFieldWidth(13); 0174 out << c->prettyCallCount(); 0175 out.setFieldWidth(0); 0176 out << " > " << c->called()->prettyName() << "\n"; 0177 } 0178 } 0179 0180 } 0181 } 0182