dvander@1908: /** dvander@1908: * vim: set ts=4 : dvander@1908: * ============================================================================= dvander@1908: * SourceMod ds@1947: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. dvander@1908: * ============================================================================= dvander@1908: * dvander@1908: * This program is free software; you can redistribute it and/or modify it under dvander@1908: * the terms of the GNU General Public License, version 3.0, as published by the dvander@1908: * Free Software Foundation. dvander@1908: * dvander@1908: * This program is distributed in the hope that it will be useful, but WITHOUT dvander@1908: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@1908: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more dvander@1908: * details. dvander@1908: * dvander@1908: * You should have received a copy of the GNU General Public License along with dvander@1908: * this program. If not, see . dvander@1908: * dvander@1908: * As a special exception, AlliedModders LLC gives you permission to link the dvander@1908: * code of this program (as well as its derivative works) to "Half-Life 2," the dvander@1908: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software dvander@1908: * by the Valve Corporation. You must obey the GNU General Public License in dvander@1908: * all respects for all other code used. Additionally, AlliedModders LLC grants dvander@1908: * this exception to all derivative works. AlliedModders LLC defines further dvander@1908: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), dvander@1908: * or . dvander@1908: * dvander@1908: * Version: $Id$ dvander@1908: */ dvander@1908: dvander@1908: #ifndef _INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_ dvander@1908: #define _INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_ dvander@1908: dvander@1908: #include dvander@1908: #include dvander@1908: #include dvander@1908: #include dvander@1908: #include dvander@1908: #include dvander@2728: #include "common_logic.h" dvander@2728: #include dvander@1908: dvander@1908: using namespace SourcePawn; dvander@1908: using namespace SourceHook; dvander@1908: dvander@1908: struct prof_point_t dvander@1908: { dvander@1908: #if defined PLATFORM_WINDOWS dvander@1908: LARGE_INTEGER value; dvander@1908: #elif defined PLATFORM_POSIX dvander@1908: struct timeval value; dvander@1908: #endif dvander@1908: bool is_set; dvander@1908: }; dvander@1908: dvander@1908: struct prof_atom_t dvander@1908: { dvander@1908: int atom_type; /* Type of object we're profiling */ dvander@1908: int atom_serial; /* Serial number, if appropriate */ dvander@1908: sp_context_t *ctx; /* Plugin context. */ dvander@1908: const char *name; /* Name of the function */ dvander@1908: prof_point_t start; /* Start time */ dvander@1908: prof_point_t end; /* End time */ dvander@1908: double base_time; /* Known time from children or pausing. */ dvander@1908: }; dvander@1908: dvander@1908: struct prof_atom_report_t dvander@1908: { dvander@1908: char atom_name[256]; /* Full name to shove to logs */ dvander@1908: double total_time; /* Total time spent executing, in s */ dvander@1908: unsigned int num_calls; /* Number of invocations */ dvander@1908: double min_time; /* Min time spent in one call, in s */ dvander@1908: double max_time; /* Max time spent in one call, in s */ dvander@1908: }; dvander@1908: dvander@1908: class ProfileReport dvander@1908: { dvander@1908: public: dvander@1908: ~ProfileReport(); dvander@1908: public: dvander@1908: void SaveAtom(const prof_atom_t &atom); dvander@1908: size_t GetNumReports(); dvander@1908: prof_atom_report_t *GetReport(size_t i); dvander@1908: void Clear(); dvander@1908: private: dvander@1908: KTrie m_ReportLookup; dvander@1908: CVector m_Reports; dvander@1908: }; dvander@1908: dvander@1908: class ProfileEngine : dvander@1908: public SMGlobalClass, dvander@1908: public IRootConsoleCommand, dvander@1908: public IProfiler dvander@1908: { dvander@1908: public: dvander@1908: ProfileEngine(); dvander@1908: public: dvander@1908: bool IsEnabled(); dvander@1908: bool GenerateReport(FILE *fp); dvander@1908: void Clear(); dvander@1908: public: //SMGlobalClass dvander@1908: void OnSourceModAllInitialized(); dvander@1908: void OnSourceModShutdown(); dvander@1908: public: //IRootConsoleCommand dvander@2728: void OnRootConsoleCommand2(const char *cmdname, const ICommandArgs *command); dvander@1908: public: //IProfiler dvander@1908: void OnNativeBegin(IPluginContext *pContext, sp_native_t *native); dvander@1908: void OnNativeEnd() ; dvander@1908: void OnFunctionBegin(IPluginContext *pContext, const char *name); dvander@1908: void OnFunctionEnd(); dvander@1908: int OnCallbackBegin(IPluginContext *pContext, sp_public_t *pubfunc); dvander@1908: void OnCallbackEnd(int serial); dvander@1908: private: dvander@1908: void PushProfileStack(IPluginContext *ctx, int type, const char *name); dvander@1908: void PopProfileStack(ProfileReport *reporter); dvander@1908: void PauseParent(); dvander@1908: void ResumeParent(double addTime); dvander@1908: void WriteReport(FILE *fp, ProfileReport *report, const char *name); dvander@1908: private: dvander@1908: CStack m_AtomStack; dvander@1908: ProfileReport m_Callbacks; dvander@1908: ProfileReport m_Functions; dvander@1908: ProfileReport m_Natives; dvander@1908: int m_serial; dvander@1908: prof_point_t m_ProfStart; dvander@1908: }; dvander@1908: dvander@2878: extern IProfiler *sm_profiler; dvander@1908: dvander@1908: #endif //_INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_