FProfilerManager::FProfilerManager( const ISessionManagerRef& InSessionManager ) : SessionManager( InSessionManager ) , CommandList( new FUICommandList() ) , ProfilerActionManager( this ) , Settings() , ProfilerType( EProfilerSessionTypes::InvalidOrMax ) , bLivePreview( false ) , bHasCaptureFileFullyProcessed( false ) { FEventGraphSample::InitializePropertyManagement(); #if 0 // Performance tests. static FTotalTimeAndCount CurrentNative(0.0f, 0); static FTotalTimeAndCount CurrentPointer(0.0f, 0); static FTotalTimeAndCount CurrentShared(0.0f, 0); for( int32 Lx = 0; Lx < 16; ++Lx ) { FRandomStream RandomStream( 666 ); TArray<FEventGraphSample> EventsNative; TArray<FEventGraphSample*> EventsPointer; TArray<FEventGraphSamplePtr> EventsShared; const int32 NumEvents = 16384; for( int32 Nx = 0; Nx < NumEvents; ++Nx ) { const double Rnd = RandomStream.FRandRange( 0.0f, 16384.0f ); const FString EventName = TTypeToString<double>::ToString( Rnd ); FEventGraphSample NativeEvent( *EventName ); NativeEvent._InclusiveTimeMS = Rnd; FEventGraphSamplePtr SharedEvent = FEventGraphSample::CreateNamedEvent( *EventName ); SharedEvent->_InclusiveTimeMS = Rnd; EventsNative.Add(NativeEvent); EventsPointer.Add(SharedEvent.Get()); EventsShared.Add(SharedEvent); } { FProfilerScopedLogTime ScopedLog( TEXT("1.NativeSorting"), &CurrentNative ); EventsNative.Sort( FEventGraphSampleLess() ); } { FProfilerScopedLogTime ScopedLog( TEXT("2PointerSorting"), &CurrentPointer ); EventsPointer.Sort( FEventGraphSampleLess() ); } { FProfilerScopedLogTime ScopedLog( TEXT("3.SharedSorting"), &CurrentShared ); FEventArraySorter::Sort( EventsShared, FEventGraphSample::GetEventPropertyByIndex(EEventPropertyIndex::InclusiveTimeMS).Name, EEventCompareOps::Less ); } } #endif // 0 }
//--------------------------------------------------------------------------- void tTVPTimerThread::Execute() { while(!GetTerminated()) { tjs_uint64 step_next = (tjs_uint64)(tjs_int64)-1L; // invalid value tjs_uint64 curtick = TVPGetTickCount() << TVP_SUBMILLI_FRAC_BITS; DWORD sleeptime; { // thread-protected tTJSCriticalSectionHolder holder(TVPTimerCS); bool any_triggered = false; std::vector<tTJSNI_Timer*>::iterator i; for(i = List.begin(); i!=List.end(); i ++) { tTJSNI_Timer * item = *i; if(!item->GetEnabled() || item->GetInterval() == 0) continue; if(item->GetNextTick() < curtick) { tjs_uint n = static_cast<tjs_uint>( (curtick - item->GetNextTick()) / item->GetInterval() ); n++; if(n > 40) { // too large amount of event at once; discard rest item->Trigger(1); any_triggered = true; item->SetNextTick(curtick + item->GetInterval()); } else { item->Trigger(n); any_triggered = true; item->SetNextTick(item->GetNextTick() + n * item->GetInterval()); } } tjs_uint64 to_next = item->GetNextTick() - curtick; if(step_next == (tjs_uint64)(tjs_int64)-1L) { step_next = to_next; } else { if(step_next > to_next) step_next = to_next; } } if(step_next != (tjs_uint64)(tjs_int64)-1L) { // too large step_next must be diminished to size of DWORD. if(step_next >= 0x80000000) sleeptime = 0x7fffffff; // smaller value than step_next is OK else sleeptime = static_cast<DWORD>( step_next ); } else { sleeptime = INFINITE; } if(List.size() == 0) sleeptime = INFINITE; if(any_triggered) { // triggered; post notification message to the UtilWindow if(!PendingEventsAvailable) { PendingEventsAvailable = true; EventQueue.PostEvent( NativeEvent(TVP_EV_TIMER_THREAD) ); } } } // end-of-thread-protected // now, sleeptime has sub-milliseconds precision but we need millisecond // precision time. if(sleeptime != INFINITE) sleeptime = (sleeptime >> TVP_SUBMILLI_FRAC_BITS) + (sleeptime & ((1<<TVP_SUBMILLI_FRAC_BITS)-1) ? 1: 0); // round up // clamp to TVP_LEAST_TIMER_INTERVAL ... if(sleeptime != INFINITE && sleeptime < TVP_LEAST_TIMER_INTERVAL) sleeptime = TVP_LEAST_TIMER_INTERVAL; Event.WaitFor(sleeptime); // wait until sleeptime is elapsed or // Event->SetEvent() is executed. } }