#pragma once #include "plug.h" #include "chain.h" #include "time.h" #include "config.h" #if defined(TRACE_ON) struct TraceSample { Scalar sampleFraction; Word sampleFrame; Byte traceNumber; Byte sampleType; enum Type { GoingUp = 0, GoingDown, Marker, IntegerSnapshot, ScalarSnapshot, SuspendSampling, ResumeSampling }; }; template struct SnapshotOf : public TraceSample { T snapShot; }; class Trace : public Plug { friend class TraceManager; public: enum Type { BitType, IntegerType, ScalarType }; protected: static Byte NextTraceID; const char *traceName; long lastFrameActivity; Scalar lastFractionActivity; Byte traceNumber; Byte traceType; Trace(const char* name, Type type); MemoryStream *GetTraceLog(); void IncrementSampleCount(); virtual void DumpTraceStatus()=0; virtual void ResetTrace()=0; #if defined(USE_TIME_ANALYSIS) virtual void StartTiming()=0; virtual Scalar CalcuateUsage(long frame, Scalar fraction, double sample_time)=0; virtual void PrintUsage(Scalar usage); #endif }; class BitTrace : public Trace { protected: static Byte NextActiveLine; Logical traceUp; double lastUpTime, totalUpTime; Byte activeLine; #if defined(USE_ACTIVE_PROFILE) static void SetLineImplementation(Byte line); static void ClearLineImplementation(Byte line); static Logical IsLineValidImplementation(Byte line); #endif void DumpTraceStatus(); void ResetTrace(); #if defined(USE_TIME_ANALYSIS) void StartTiming(); Scalar CalculateUsage(long frame, Scalar fraction, double sample_time); void PrintUsage(Scalar usage); #endif public: BitTrace(const char *name); void Set(); void Clear(); double GetLastUpTime() { Check(this); return lastUpTime; } double GetTotalUpTime() { Check(this); return totalUpTime; } }; template class TraceOf : public Trace { protected: double weightedSum; T currentValue; TraceSample::Type sampleType; void DumpTraceStatus(); void ResetTrace(); #if defined(USE_TIME_ANALYSIS) void StartTiming(); Scalar CalculateUsage(long frame, Scalar fraction, double sample_time); void PrintUsage(Scalar usage); #endif public: TraceOf(const char* name, const T& initial_value, Type trace_type, TraceSample::Type sample_type); void TakeSnapshot(const T& value); }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // template TraceOf::TraceOf(const char* name, const T& initial_value, Type trace_type, TraceSample::Type sample_type) : Trace(name, trace_type) { currentValue = initial_value; sampleType = sample_type; TraceOf::ResetTrace(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // template void TraceOf::DumpTraceStatus() { Check(this); DEBUG_STREAM << currentValue << std::flush; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // template void TraceOf::ResetTrace() { #if defined(USE_TIME_ANALYSIS) weightedSum = 0.0; #endif } #if defined(USE_TIME_ANALYSIS) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // template void TraceOf::StartTiming() { Check(this); weightedSum = 0.0; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // template Scalar TraceOf::CalculateUsage(long frame, Scalar fraction, double sample_time) { double last_part = frame - lastFrameActivity; last_part += fraction - lastFractionActivity; weightedSum += last_part * currentValue; Scalar result = weightedSum / sample_time; Check_Fpu(); weightedSum = 0.0; return result; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // template void TraceOf::PrintUsage(Scalar usage) { Check(this); DEBUG_STREAM << usage << std::flush; } #endif //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // template void TraceOf::TakeSnapshot(const T& value) { Check(this); #if defined(USE_TIME_ANALYSIS) || defined(USE_TRACE_LOG) long frame = Now().ticks; Scalar fraction = Get_Frame_Percent_Used(); #endif #if defined(USE_TIME_ANALYSIS) double last_part = frame - lastFrameActivity; last_part += fraction - lastFractionActivity; weightedSum += last_part * currentValue; lastFrameActivity = frame; lastFractionActivity = fraction; #endif currentValue = value; #if defined(USE_TRACE_LOG) IncrementSampleCount(); MemoryStream *log = GetTraceLog(); if (log) { Check(log); SnapshotOf *sample = (SnapshotOf*)log->GetPointer(); sample->sampleType = (Byte)sampleType; sample->traceNumber = traceNumber; sample->sampleFrame = (Word)frame; sample->sampleFraction = fraction; sample->snapShot = currentValue; log->AdvancePointer(sizeof(*sample)); } #endif } //####################################################################### //##################### TraceManager ############################## //####################################################################### class TraceManager SIGNATURED { friend class Trace; protected: ChainOf traceChain; long sampleStartFrame; Scalar sampleStartFraction; int actualSampleCount, ignoredSampleCount; MemoryStream *allocatedTraceLog, *activeTraceLog; Byte traceCount; void Add(Trace *trace); public: TraceManager(); ~TraceManager(); Byte GetTraceCount() { Check(this); return traceCount; } void DumpTracesStatus(); void ResetTraces(); #if defined(USE_TIME_ANALYSIS) void StartTimingAnalysis(); int SnapshotTimingAnalysis(Logical print = false); #endif #if defined(USE_TRACE_LOG) void CreateTraceLog(size_t max_trace_samples, Logical start_sampling); void SaveTraceLog(const char* filename); void MarkTraceLog(); void SuspendTraceLogging(); void ResumeTraceLogging(); #endif Logical TestInstance() const; }; extern TraceManager trace_manager; inline MemoryStream* Trace::GetTraceLog() { Check(this); Check(&trace_manager); return trace_manager.activeTraceLog; } inline void Trace::IncrementSampleCount() { Check(this); Check(&trace_manager); if (!trace_manager.activeTraceLog) ++trace_manager.ignoredSampleCount; else ++trace_manager.actualSampleCount; } # endif