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@1908: #include "sm_globals.h"
dvander@1908: #include "sm_srvcmds.h"
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@1908: void OnRootConsoleCommand(const char *cmdname, const CCommand &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@1908: extern ProfileEngine g_Profiler;
dvander@1908:
dvander@1908: #endif //_INCLUDE_SOURCEMOD_PLUGIN_PROFILER_H_