/* ----------------------------------------------------------------------------- GSFramework Copyright 2001-2013 Emmanuel Julien. All Rights Reserved. ----------------------------------------------------------------------------- */ #include "script/script_profiler.h" #include "platform.h" #include "log/log.h" using namespace GS::Script; //------------------------------------------------------------------------------ Profiler::FunctionProfile *Profiler::GetFunctionProfile(const char *source, const char *func, int line, FunctionProfile *caller) { // Check for profiled function. FunctionProfile *profile = NULL; ListForeachPtr(FunctionProfile *, f_profile, function_map) if ( (f_profile->func == func) && (f_profile->caller_function == caller) ) { profile = f_profile; break; } // Create a new function profile. if (!profile) { profile = new FunctionProfile(source, func, line); if (!profile) __LOG_E__ << "Failed to allocate a new function profile.\n"; // Register caller. profile->caller_function = caller; // Add the newly created function as a child of the caller function profile. if (caller) caller->callee_function.Add(profile); function_map.Add(profile); } return profile; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void Profiler::Start(const char *session_id) { id = session_id; function_map.Clear(); function_list.Clear(); current_function_profile = NULL; profiler_clock = Platform::Get().GetClock(); total_clock = 0; profiling = true; } int Profiler::GetChildTotalClock(FunctionProfile *profile) { int child_total_clock = 0; ListForeachPtr(FunctionProfile *, c_profile, profile->callee_function) child_total_clock += GetChildTotalClock(c_profile); return profile->self_clock + child_total_clock; } void Profiler::End() { ListForeachPtr(FunctionProfile *, f_profile, function_map) f_profile->total_clock = GetChildTotalClock(f_profile); // Build the function list from the call graph function map. ListForeachPtr(FunctionProfile *, f_profile, function_map) { // Check list if function is already present. FunctionProfile *profile = NULL; ListForeachPtr(FunctionProfile *, l_profile, function_list) if (l_profile->func == f_profile->func) { profile = l_profile; break; } // If not, create a new list entry. if (!profile) { profile = new FunctionProfile(f_profile->source.c_str(), f_profile->func.c_str(), f_profile->line); function_list.Add(profile); } // Merge this function contribution. profile->hit_count += f_profile->hit_count; profile->self_clock += f_profile->self_clock; profile->total_clock += f_profile->total_clock; } profiling = false; } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ void Profiler::Update(int type, FunctionProfile *profile) { // Update clock. int current_clock = Platform::Get().GetClock(), dt_clock = current_clock - profiler_clock; profiler_clock = current_clock; // Update current profile. if (current_function_profile) { current_function_profile->Update(dt_clock, 0); total_clock += dt_clock; } // Get profile. switch (type) { case 'c': current_function_profile = profile; current_function_profile->Hit(); break; case 'r': current_function_profile = NULL; break; case 'l': break; } } //------------------------------------------------------------------------------ Profiler::Profiler() : profiling(false), current_function_profile(NULL) {}