diff options
author | Jon Ashburn <jon@lunarg.com> | 2014-08-11 15:35:35 -0600 |
---|---|---|
committer | José Fonseca <jfonseca@vmware.com> | 2014-09-04 23:04:41 +0100 |
commit | 4ab49b87b42620612ad4aa151c04ab5c4d7b2b19 (patch) | |
tree | b392602b0fe566273f6ac0934eeb083c084c7830 | |
parent | e6a50cc3998fe7f3210c0170abd8c805eba638db (diff) |
glretrace: When looping on replay save parsed calls for faster executionloop
Since the Call class is deleted after replaying each call, the saved calls
had to copy this class and remain undeleted. This required supporting
infastructure to clone the class Call and not delete this class
for the saved calls except when done looping.
-rw-r--r-- | cli/cli_dump.cpp | 6 | ||||
-rw-r--r-- | cli/cli_pickle.cpp | 6 | ||||
-rw-r--r-- | cli/cli_retrace.cpp | 6 | ||||
-rw-r--r-- | cli/cli_sed.cpp | 6 | ||||
-rw-r--r-- | cli/cli_trim.cpp | 17 | ||||
-rw-r--r-- | common/trace_loader.cpp | 3 | ||||
-rw-r--r-- | common/trace_model.cpp | 41 | ||||
-rw-r--r-- | common/trace_model.hpp | 49 | ||||
-rw-r--r-- | common/trace_parser.cpp | 36 | ||||
-rw-r--r-- | common/trace_parser.hpp | 46 | ||||
-rw-r--r-- | gui/saverthread.cpp | 3 | ||||
-rw-r--r-- | gui/traceloader.cpp | 22 | ||||
-rw-r--r-- | retrace/retrace_main.cpp | 17 |
13 files changed, 209 insertions, 49 deletions
diff --git a/cli/cli_dump.cpp b/cli/cli_dump.cpp index d674c83d..4c64001c 100644 --- a/cli/cli_dump.cpp +++ b/cli/cli_dump.cpp @@ -178,14 +178,16 @@ command(int argc, char *argv[]) } trace::Call *call; - while ((call = p.parse_call())) { + bool delCall; + while ((call = p.parse_call(delCall))) { if (calls.contains(*call)) { if (verbose || !(call->flags & trace::CALL_FLAG_VERBOSE)) { trace::dump(*call, std::cout, dumpFlags); } } - delete call; + if (delCall) + delete call; } } diff --git a/cli/cli_pickle.cpp b/cli/cli_pickle.cpp index e7f51ff9..46a5f31d 100644 --- a/cli/cli_pickle.cpp +++ b/cli/cli_pickle.cpp @@ -271,13 +271,15 @@ command(int argc, char *argv[]) } trace::Call *call; - while ((call = parser.parse_call())) { + bool delCall; + while ((call = parser.parse_call(delCall))) { if (calls.contains(*call)) { writer.begin(); visitor.visit(call); writer.end(); } - delete call; + if(delCall) + delete call; } } diff --git a/cli/cli_retrace.cpp b/cli/cli_retrace.cpp index db799b96..432ed472 100644 --- a/cli/cli_retrace.cpp +++ b/cli/cli_retrace.cpp @@ -50,8 +50,10 @@ guessApi(const char *filename) return trace::API_UNKNOWN; } trace::Call *call; - while ((call = p.parse_call())) { - delete call; + bool delCall; + while ((call = p.parse_call(delCall))) { + if (delCall) + delete call; if (p.api != trace::API_UNKNOWN) { return p.api; diff --git a/cli/cli_sed.cpp b/cli/cli_sed.cpp index afec1257..b33130f4 100644 --- a/cli/cli_sed.cpp +++ b/cli/cli_sed.cpp @@ -189,7 +189,8 @@ sed_trace(Replacements &replacements, const char *inFileName, std::string &outFi } trace::Call *call; - while ((call = p.parse_call())) { + bool delCall; + while ((call = p.parse_call(delCall))) { for (Replacements::iterator it = replacements.begin(); it != replacements.end(); ++it) { it->visit(call); @@ -197,7 +198,8 @@ sed_trace(Replacements &replacements, const char *inFileName, std::string &outFi writer.writeCall(call); - delete call; + if (delCall) + delete call; } std::cerr << "Edited trace is available as " << outFileName << "\n"; diff --git a/cli/cli_trim.cpp b/cli/cli_trim.cpp index ed950e5c..ed8900fc 100644 --- a/cli/cli_trim.cpp +++ b/cli/cli_trim.cpp @@ -220,14 +220,16 @@ trim_trace(const char *filename, struct trim_options *options) /* In pass 1, analyze which calls are needed. */ frame = 0; trace::Call *call; - while ((call = p.parse_call())) { + bool delCall; + while ((call = p.parse_call(delCall))) { /* There's no use doing any work past the last call and frame * requested by the user. */ if ((options->calls.empty() || call->no > options->calls.getLast()) && (options->frames.empty() || frame > options->frames.getLast())) { - delete call; + if (delCall) + delete call; break; } @@ -262,7 +264,8 @@ trim_trace(const char *filename, struct trim_options *options) if (call->flags & trace::CALL_FLAG_END_FRAME) frame++; - delete call; + if (delCall) + delete call; } /* Prepare output file and writer for output. */ @@ -288,14 +291,15 @@ trim_trace(const char *filename, struct trim_options *options) frame = 0; call_range_first = -1; call_range_last = -1; - while ((call = p.parse_call())) { + while ((call = p.parse_call(delCall))) { /* There's no use doing any work past the last call and frame * requested by the user. */ if ((options->calls.empty() || call->no > options->calls.getLast()) && (options->frames.empty() || frame > options->frames.getLast())) { - delete call; + if (delCall) + delete call; break; } @@ -320,7 +324,8 @@ trim_trace(const char *filename, struct trim_options *options) frame++; } - delete call; + if (delCall) + delete call; } if (options->print_callset) { diff --git a/common/trace_loader.cpp b/common/trace_loader.cpp index 6a3d7de0..7a355924 100644 --- a/common/trace_loader.cpp +++ b/common/trace_loader.cpp @@ -120,7 +120,8 @@ std::vector<trace::Call *> Loader::frame(unsigned idx) trace::Call *call; unsigned parsedCalls = 0; - while ((call = m_parser.parse_call())) { + bool delCall; + while ((call = m_parser.parse_call(delCall))) { calls[parsedCalls] = call; ++parsedCalls; diff --git a/common/trace_model.cpp b/common/trace_model.cpp index baebc18f..8619d030 100644 --- a/common/trace_model.cpp +++ b/common/trace_model.cpp @@ -203,6 +203,47 @@ void Blob ::visit(Visitor &visitor) { visitor.visit(this); } void Pointer::visit(Visitor &visitor) { visitor.visit(this); } void Repr ::visit(Visitor &visitor) { visitor.visit(this); } +// virtual Value::clone +Value * Null::clone() const { return new Null(*this);} +Value * Bool::clone() const { return new Bool(*this);} +Value * SInt::clone() const { return new SInt(*this);} +Value * UInt::clone() const { return new UInt(*this);} +Value * Float::clone() const { return new Float(*this);} +Value * Double::clone() const { return new Double(*this);} +Value * Enum::clone() const { return new Enum(*this);} +Value * Bitmask::clone() const { return new Bitmask(*this);} +Value * Pointer::clone() const { return new Pointer(*this);} +Value * Repr::clone() const { return new Repr(*this);} +Value * String::clone() const +{ + String *str = new String(*this); + char *val = new char [strlen(this->value) + 1]; + strcpy(val, this->value); + return str; +} +Value * Struct::clone() const +{ + Struct *temp = new Struct(*this); + for (std::vector<Value *>::size_type i = 0; i != members.size(); i++) { + temp->members[i] = members[i]->clone(); + } + return temp; +} +Value * Array::clone() const +{ + Array *temp = new Array(*this); + for (std::vector<Value *>::size_type i = 0; i != values.size(); i++) { + temp->values[i] = values[i]->clone(); + } + return temp; +} +Value * Blob::clone() const +{ + Blob *temp = new Blob(*this); + if (bound) + memcpy(temp->buf,this->buf, size); + return temp; +} void Visitor::visit(Null *) { assert(0); } void Visitor::visit(Bool *) { assert(0); } diff --git a/common/trace_model.hpp b/common/trace_model.hpp index 164b1ab4..a8470d30 100644 --- a/common/trace_model.hpp +++ b/common/trace_model.hpp @@ -102,7 +102,7 @@ class Value public: virtual ~Value() {} virtual void visit(Visitor &visitor) = 0; - + virtual Value *clone() const = 0; virtual bool toBool(void) const = 0; virtual signed long long toSInt(void) const; virtual unsigned long long toUInt(void) const; @@ -140,6 +140,7 @@ public: unsigned long long toUIntPtr(void) const; const char *toString(void) const; void visit(Visitor &visitor); + Value *clone() const; const Null *toNull(void) const { return this; } Null *toNull(void) { return this; } @@ -157,7 +158,8 @@ public: virtual float toFloat(void) const; virtual double toDouble(void) const; void visit(Visitor &visitor); - + Value *clone() const; + bool value; }; @@ -173,7 +175,8 @@ public: virtual float toFloat(void) const; virtual double toDouble(void) const; void visit(Visitor &visitor); - + Value *clone() const; + signed long long value; }; @@ -189,7 +192,8 @@ public: virtual float toFloat(void) const; virtual double toDouble(void) const; void visit(Visitor &visitor); - + Value *clone() const; + unsigned long long value; }; @@ -205,7 +209,8 @@ public: virtual float toFloat(void) const; virtual double toDouble(void) const; void visit(Visitor &visitor); - + Value *clone() const; + float value; }; @@ -221,7 +226,8 @@ public: virtual float toFloat(void) const; virtual double toDouble(void) const; void visit(Visitor &visitor); - + Value *clone() const; + double value; }; @@ -235,7 +241,8 @@ public: bool toBool(void) const; const char *toString(void) const; void visit(Visitor &visitor); - + Value *clone() const; + const char * value; }; @@ -246,6 +253,7 @@ public: Enum(const EnumSig *_sig, signed long long _value) : SInt(_value), sig(_sig) {} void visit(Visitor &visitor); + Value *clone() const; const EnumSig *sig; @@ -268,6 +276,7 @@ public: Bitmask(const BitmaskSig *_sig, unsigned long long _value) : UInt(_value), sig(_sig) {} void visit(Visitor &visitor); + Value *clone() const; const BitmaskSig *sig; }; @@ -281,7 +290,8 @@ public: bool toBool(void) const; void visit(Visitor &visitor); - + Value *clone() const; + const Struct *toStruct(void) const { return this; } Struct *toStruct(void) { return this; } @@ -298,7 +308,8 @@ public: bool toBool(void) const; void visit(Visitor &visitor); - + Value *clone() const; + const Array *toArray(void) const { return this; } Array *toArray(void) { return this; } @@ -326,7 +337,8 @@ public: void *toPointer(void) const; void *toPointer(bool bind); void visit(Visitor &visitor); - + Value *clone() const; + size_t size; char *buf; bool bound; @@ -343,6 +355,7 @@ public: void *toPointer(bool bind); unsigned long long toUIntPtr(void) const; void visit(Visitor &visitor); + Value *clone() const; }; @@ -372,6 +385,7 @@ public: virtual const char *toString(void) const; void visit(Visitor &visitor); + Value *clone() const; }; struct RawStackFrame { @@ -549,7 +563,20 @@ public: flags(_flags), backtrace(0) { } - + Call(const Call *other) : thread_id(other->thread_id), no(other->no), + sig(other->sig), args(other->args), ret(0), flags(other->flags), + backtrace(0) + { + for (int i = 0; i < other->args.size(); i++) { + Value *a = other->args[i].value->clone(); + args[i].value = a; + } + + if (other->ret) { + ret = other->ret->clone(); + } + } + ~Call(); inline const char * diff --git a/common/trace_parser.cpp b/common/trace_parser.cpp index f5c6f1d3..45d6699a 100644 --- a/common/trace_parser.cpp +++ b/common/trace_parser.cpp @@ -1023,10 +1023,19 @@ void LastFrameLoopParser::bookmarkFrameStart(trace::Call *call) { } } -Call *LastFrameLoopParser::parse_call(void) { +Call *LastFrameLoopParser::parse_call(bool & del) { trace::Call *call; - call = parser->parse_call(); + call = parser->parse_call(del); + if (savingCalls) { + if (call) { + trace::Call * tempCall = new Call(call); + savedCalls.push_back(tempCall); + } else { + savedCalls.push_back(call); + } + } + /* If the user wants to loop we need to get a bookmark target. We * usually get this after replaying a call that ends a frame, but @@ -1039,7 +1048,21 @@ Call *LastFrameLoopParser::parse_call(void) { /* Restart last frame when looping is requested. */ if (!call && (loopIter > 0 || loopContinuous)) { parser->setBookmark(lastFrameStart); - call = parser->parse_call(); + call = parser->parse_call(del); + /* If looping multiple times save parsed calls on first loop so + * subsequent loops will run faster. */ + if (savedCalls.empty() && !savingCalls && (loopIter > 1 || loopContinuous)) { + savingCalls = true; + trace::Call *tempCall = new Call(call); + savedCalls.push_back(tempCall); + } else if (savingCalls) { + /* any subsequent loops use fast parser */ + parser = new FastParser(parser, &savedCalls); + fp = parser; + savingCalls = false; + call = parser->parse_call(del); + + } if (!loopContinuous) loopIter--; } else if (callEndsFrame) { @@ -1049,5 +1072,12 @@ Call *LastFrameLoopParser::parse_call(void) { return call; } +Call * FastParser::parse_call(bool &del) { + Call *temp; + idx = idx % savedCalls->size(); + temp = (*savedCalls)[idx++]; + del = false; + return temp; +} } /* namespace trace */ diff --git a/common/trace_parser.hpp b/common/trace_parser.hpp index a86f35dc..08b35380 100644 --- a/common/trace_parser.hpp +++ b/common/trace_parser.hpp @@ -3,7 +3,7 @@ * Copyright 2010 VMware, Inc. * All Rights Reserved. * - * Permission is hereby granted, free of charge, to any person obtaining a copy + * Permission is hereby granted,free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell @@ -54,7 +54,7 @@ struct ParseBookmark { public: virtual ~AbstractParser() {} - virtual Call *parse_call(void) = 0; + virtual Call *parse_call(bool &del) = 0; virtual void bookmarkFrameStart(trace::Call *call) = 0; virtual void getBookmark(ParseBookmark &bookmark) = 0; virtual void setBookmark(const ParseBookmark &bookmark) = 0; @@ -125,7 +125,8 @@ public: void close(void); - Call *parse_call(void) { + Call *parse_call(bool & del) { + del = true; return parse_call(FULL); } @@ -238,6 +239,29 @@ protected: inline void skip_byte(void); }; +// Decorator to loop over a vector of saved calls +class FastParser: public AbstractParser { +public: + FastParser(AbstractParser *p, std::vector<Call *> *s) { + parser = p; + savedCalls = s; + idx = 0; + } + ~FastParser() {} + + Call *parse_call(bool &del); + void bookmarkFrameStart(trace::Call *call) {} + void getBookmark(ParseBookmark &bookmark) {} + void setBookmark(const ParseBookmark &bookmark) {} + bool open(const char *filename) {return false;} + void close(void) {} + unsigned long long get_version(void) {return 0;} +private: + AbstractParser *parser; + std::vector<Call *> *savedCalls; + unsigned int idx; +}; + // Decorator for parser which loops class LastFrameLoopParser : public AbstractParser { public: @@ -245,10 +269,19 @@ public: parser = p; callEndsFrame = false; firstCall = true; + savedCalls.clear(); + savingCalls = false; + fp = NULL; + } + ~LastFrameLoopParser() { + delete fp; + fp = NULL; + for (std::vector<Call *>::iterator it = savedCalls.begin(); it != savedCalls.end();) + it = savedCalls.erase(it); + savedCalls.clear(); } - ~LastFrameLoopParser() { delete parser; } - Call *parse_call(void); + Call *parse_call(bool & del); void bookmarkFrameStart(trace::Call *call); //delegate to Parser @@ -259,9 +292,12 @@ public: unsigned long long get_version(void) {return parser->get_version();} private: AbstractParser *parser; + AbstractParser *fp; bool callEndsFrame, firstCall; ParseBookmark frameStart; ParseBookmark lastFrameStart; + std::vector<Call *> savedCalls; + bool savingCalls; }; } /* namespace trace */ diff --git a/gui/saverthread.cpp b/gui/saverthread.cpp index 4ad83c58..a7a42788 100644 --- a/gui/saverthread.cpp +++ b/gui/saverthread.cpp @@ -353,7 +353,8 @@ void SaverThread::run() parser.open(m_readFileName.toLocal8Bit()); trace::Call *call; - while ((call = parser.parse_call())) { + bool delCall; + while ((call = parser.parse_call(delCall))) { if (callIndexMap.contains(call->no)) { QVector<QVariant> values = callIndexMap[call->no]->editedValues(); for (int i = 0; i < values.count(); ++i) { diff --git a/gui/traceloader.cpp b/gui/traceloader.cpp index 59f8803e..10139e64 100644 --- a/gui/traceloader.cpp +++ b/gui/traceloader.cpp @@ -265,7 +265,8 @@ void TraceLoader::searchNext(const ApiTrace::SearchRequest &request) const FrameBookmark &frameBookmark = m_frameBookmarks[startFrame]; m_parser.setBookmark(frameBookmark.start); trace::Call *call = 0; - while ((call = m_parser.parse_call())) { + bool delCall; + while ((call = m_parser.parse_call(delCall))) { if (callContains(call, request.text, request.cs)) { unsigned frameIdx = callInFrame(call->no); @@ -279,11 +280,13 @@ void TraceLoader::searchNext(const ApiTrace::SearchRequest &request) break; } } - delete call; + if (delCall) + delete call; return; } - delete call; + if (delCall) + delete call; } } emit searchResult(request, ApiTrace::SearchResult_NotFound, 0); @@ -301,8 +304,9 @@ void TraceLoader::searchPrev(const ApiTrace::SearchRequest &request) const FrameBookmark &frameBookmark = m_frameBookmarks[frameIdx]; int numCallsToParse = frameBookmark.numberOfCalls; m_parser.setBookmark(frameBookmark.start); - - while ((call = m_parser.parse_call())) { + + bool delCall; + while ((call = m_parser.parse_call(delCall))) { frameCalls.append(call); --numCallsToParse; @@ -528,8 +532,9 @@ TraceLoader::FrameContents::load(TraceLoader *loader, int initNumOfCalls = m_allCalls.count(); trace::Call *call; ApiTraceCall *apiCall = NULL; - - while ((call = parser.parse_call())) { + bool delCall; + + while ((call = parser.parse_call(delCall))) { apiCall = apiCallFromTraceCall(call, helpHash, currentFrame, m_groups.isEmpty() ? 0 : m_groups.top(), @@ -561,7 +566,8 @@ TraceLoader::FrameContents::load(TraceLoader *loader, m_binaryDataSize += data.size(); } - delete call; + if (delCall) + delete call; if (apiCall->flags() & trace::CALL_FLAG_END_FRAME) { bEndFrameReached = true; diff --git a/retrace/retrace_main.cpp b/retrace/retrace_main.cpp index ce6fea43..814bd4eb 100644 --- a/retrace/retrace_main.cpp +++ b/retrace/retrace_main.cpp @@ -325,6 +325,7 @@ public: void runLeg(trace::Call *call) { + bool delCall = true; /* Consume successive calls for this thread. */ do { @@ -334,8 +335,9 @@ public: parser->bookmarkFrameStart(call); retraceCall(call); - delete call; - call = parser->parse_call(); + if (delCall) + delete call; + call = parser->parse_call(delCall); } while (call && call->thread_id == leg); @@ -438,7 +440,8 @@ RelayRace::getRunner(unsigned leg) { void RelayRace::run(void) { trace::Call *call; - call = parser->parse_call(); + bool delCall; + call = parser->parse_call(delCall); if (!call) { /* Nothing to do */ return; @@ -507,12 +510,14 @@ mainLoop() { if (singleThread) { trace::Call *call; - call = parser->parse_call(); + bool delCall; + call = parser->parse_call(delCall); do { parser->bookmarkFrameStart(call); retraceCall(call); - delete call; - call = parser->parse_call(); + if (delCall) + delete call; + call = parser->parse_call(delCall); } while (call); } else { RelayRace race; |