core/smn_profiler.cpp
author "David Anderson <dvander@alliedmods.net>
Thu May 14 11:38:50 2009 -0400 (2009-05-14)
changeset 2730 a2ff0a7a1c53
parent 2289 44045ead61cd
child 2789 9011c2fee99b
permissions -rw-r--r--
Moved smn_functions to logic binary.
     1 /**
     2  * vim: set ts=4 :
     3  * =============================================================================
     4  * SourceMod
     5  * Copyright (C) 2004-2008 AlliedModders LLC.  All rights reserved.
     6  * =============================================================================
     7  *
     8  * This program is free software; you can redistribute it and/or modify it under
     9  * the terms of the GNU General Public License, version 3.0, as published by the
    10  * Free Software Foundation.
    11  * 
    12  * This program is distributed in the hope that it will be useful, but WITHOUT
    13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
    14  * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
    15  * details.
    16  *
    17  * You should have received a copy of the GNU General Public License along with
    18  * this program.  If not, see <http://www.gnu.org/licenses/>.
    19  *
    20  * As a special exception, AlliedModders LLC gives you permission to link the
    21  * code of this program (as well as its derivative works) to "Half-Life 2," the
    22  * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
    23  * by the Valve Corporation.  You must obey the GNU General Public License in
    24  * all respects for all other code used.  Additionally, AlliedModders LLC grants
    25  * this exception to all derivative works.  AlliedModders LLC defines further
    26  * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
    27  * or <http://www.sourcemod.net/license.php>.
    28  *
    29  * Version: $Id$
    30  */
    31 
    32 #include "sm_globals.h"
    33 #include "HandleSys.h"
    34 
    35 //Note: Do not add this to Linux yet, i haven't done the HPET timing research (if even available)
    36 //nonetheless we need accurate counting
    37 #if defined PLATFORM_LINUX
    38 #error "Not supported"
    39 #endif
    40 
    41 struct Profiler
    42 {
    43 	Profiler()
    44 	{
    45 		started = false;
    46 		stopped = false;
    47 	}
    48 #if defined PLATFORM_WINDOWS
    49 	LARGE_INTEGER start;
    50 	LARGE_INTEGER end;
    51 	double freq;
    52 #endif
    53 	bool started;
    54 	bool stopped;
    55 };
    56 
    57 HandleType_t g_ProfilerType = 0;
    58 
    59 class ProfilerHelpers : 
    60 	public SMGlobalClass,
    61 	public IHandleTypeDispatch
    62 {
    63 public:
    64 	void OnSourceModAllInitialized()
    65 	{
    66 		g_ProfilerType = g_HandleSys.CreateType("Profiler", this, 0, NULL, NULL, g_pCoreIdent, NULL);
    67 	}
    68 	void OnSourceModShutdown()
    69 	{
    70 		g_HandleSys.RemoveType(g_ProfilerType, g_pCoreIdent);
    71 	}
    72 	void OnHandleDestroy(HandleType_t type, void *object)
    73 	{
    74 		Profiler *prof = (Profiler *)object;
    75 		delete prof;
    76 	}
    77 } s_ProfHelpers;
    78 
    79 static cell_t CreateProfiler(IPluginContext *pContext, const cell_t *params)
    80 {
    81 	Profiler *p = new Profiler();
    82 
    83 #if defined PLATFORM_WINDOWS
    84 	LARGE_INTEGER qpf;
    85 	QueryPerformanceFrequency(&qpf);
    86 	p->freq = 1.0 / (double)(qpf.QuadPart);
    87 #endif
    88 
    89 	Handle_t hndl = g_HandleSys.CreateHandle(g_ProfilerType, p, pContext->GetIdentity(), g_pCoreIdent, NULL);
    90 	if (hndl == BAD_HANDLE)
    91 	{
    92 		delete p;
    93 	}
    94 
    95 	return hndl;
    96 }
    97 
    98 static cell_t StartProfiling(IPluginContext *pContext, const cell_t *params)
    99 {
   100 	Handle_t hndl = params[1];
   101 	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
   102 	HandleError err;
   103 	Profiler *prof;
   104 
   105 	if ((err = g_HandleSys.ReadHandle(hndl, g_ProfilerType, &sec, (void **)&prof))
   106 		!= HandleError_None)
   107 	{
   108 		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
   109 	}
   110 
   111 #if defined PLATFORM_WINDOWS
   112 	QueryPerformanceCounter(&prof->start);
   113 #endif
   114 
   115 	prof->started = true;
   116 	prof->stopped = false;
   117 
   118 	return 1;
   119 }
   120 
   121 static cell_t StopProfiling(IPluginContext *pContext, const cell_t *params)
   122 {
   123 	Handle_t hndl = params[1];
   124 	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
   125 	HandleError err;
   126 	Profiler *prof;
   127 
   128 	if ((err = g_HandleSys.ReadHandle(hndl, g_ProfilerType, &sec, (void **)&prof))
   129 		!= HandleError_None)
   130 	{
   131 		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
   132 	}
   133 
   134 	if (!prof->started)
   135 	{
   136 		return pContext->ThrowNativeError("Profiler was never started");
   137 	}
   138 
   139 #if defined PLATFORM_WINDOWS
   140 	QueryPerformanceCounter(&prof->end);
   141 #endif
   142 
   143 	prof->started = false;
   144 	prof->stopped = true;
   145 
   146 	return 1;
   147 }
   148 
   149 static cell_t GetProfilerTime(IPluginContext *pContext, const cell_t *params)
   150 {
   151 	Handle_t hndl = params[1];
   152 	HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent);
   153 	HandleError err;
   154 	Profiler *prof;
   155 
   156 	if ((err = g_HandleSys.ReadHandle(hndl, g_ProfilerType, &sec, (void **)&prof))
   157 		!= HandleError_None)
   158 	{
   159 		return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err);
   160 	}
   161 
   162 	if (!prof->stopped)
   163 	{
   164 		return pContext->ThrowNativeError("Profiler was never stopped");
   165 	}
   166 
   167 	float fTime;
   168 
   169 #if defined PLATFORM_WINDOWS
   170 	LONGLONG diff = prof->end.QuadPart - prof->start.QuadPart;
   171 	double seconds = diff * prof->freq;
   172 	fTime = (float)seconds;
   173 #endif
   174 
   175 	return sp_ftoc(fTime);
   176 }
   177 
   178 REGISTER_NATIVES(profilerNatives)
   179 {
   180 	{"CreateProfiler",			CreateProfiler},
   181 	{"GetProfilerTime",			GetProfilerTime},
   182 	{"StartProfiling",			StartProfiling},
   183 	{"StopProfiling",			StopProfiling},
   184 	{NULL,						NULL},
   185 };