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