dvander@3270: /** dvander@3270: * vim: set ts=4 : dvander@3270: * ============================================================================= dvander@3270: * SourceMod dvander@3270: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved. dvander@3270: * ============================================================================= dvander@3270: * dvander@3270: * This program is free software; you can redistribute it and/or modify it under dvander@3270: * the terms of the GNU General Public License, version 3.0, as published by the dvander@3270: * Free Software Foundation. dvander@3270: * dvander@3270: * This program is distributed in the hope that it will be useful, but WITHOUT dvander@3270: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS dvander@3270: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more dvander@3270: * details. dvander@3270: * dvander@3270: * You should have received a copy of the GNU General Public License along with dvander@3270: * this program. If not, see . dvander@3270: * dvander@3270: * As a special exception, AlliedModders LLC gives you permission to link the dvander@3270: * code of this program (as well as its derivative works) to "Half-Life 2," the dvander@3270: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software dvander@3270: * by the Valve Corporation. You must obey the GNU General Public License in dvander@3270: * all respects for all other code used. Additionally, AlliedModders LLC grants dvander@3270: * this exception to all derivative works. AlliedModders LLC defines further dvander@3270: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007), dvander@3270: * or . dvander@3270: * dvander@3270: * Version: $Id$ dvander@3270: */ dvander@3270: dvander@3270: #include "common_logic.h" dvander@3270: #include dvander@3270: #if !defined PLATFORM_WINDOWS dvander@3270: #include dvander@3270: #include dvander@3270: #include dvander@3270: #endif dvander@3270: dvander@3270: struct Profiler dvander@3270: { dvander@3270: Profiler() dvander@3270: { dvander@3270: started = false; dvander@3270: stopped = false; dvander@3270: } dvander@3270: #if defined PLATFORM_WINDOWS dvander@3270: LARGE_INTEGER start; dvander@3270: LARGE_INTEGER end; dvander@3270: double freq; dvander@3270: #else dvander@3270: struct timeval start; dvander@3270: struct timeval end; dvander@3270: #endif dvander@3270: bool started; dvander@3270: bool stopped; dvander@3270: }; dvander@3270: dvander@3270: HandleType_t g_ProfilerType = 0; dvander@3270: dvander@3270: class ProfilerHelpers : dvander@3270: public SMGlobalClass, dvander@3270: public IHandleTypeDispatch dvander@3270: { dvander@3270: public: dvander@3270: void OnSourceModAllInitialized() dvander@3270: { dvander@3270: g_ProfilerType = handlesys->CreateType("Profiler", this, 0, NULL, NULL, g_pCoreIdent, NULL); dvander@3270: } dvander@3270: void OnSourceModShutdown() dvander@3270: { dvander@3270: handlesys->RemoveType(g_ProfilerType, g_pCoreIdent); dvander@3270: } dvander@3270: void OnHandleDestroy(HandleType_t type, void *object) dvander@3270: { dvander@3270: Profiler *prof = (Profiler *)object; dvander@3270: delete prof; dvander@3270: } dvander@3270: } s_ProfHelpers; dvander@3270: dvander@3270: static cell_t CreateProfiler(IPluginContext *pContext, const cell_t *params) dvander@3270: { dvander@3270: Profiler *p = new Profiler(); dvander@3270: dvander@3270: #if defined PLATFORM_WINDOWS dvander@3270: LARGE_INTEGER qpf; dvander@3270: QueryPerformanceFrequency(&qpf); dvander@3270: p->freq = 1.0 / (double)(qpf.QuadPart); dvander@3270: #endif dvander@3270: dvander@3270: Handle_t hndl = handlesys->CreateHandle(g_ProfilerType, p, pContext->GetIdentity(), g_pCoreIdent, NULL); dvander@3270: if (hndl == BAD_HANDLE) dvander@3270: { dvander@3270: delete p; dvander@3270: } dvander@3270: dvander@3270: return hndl; dvander@3270: } dvander@3270: dvander@3270: static cell_t StartProfiling(IPluginContext *pContext, const cell_t *params) dvander@3270: { dvander@3270: Handle_t hndl = params[1]; dvander@3270: HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent); dvander@3270: HandleError err; dvander@3270: Profiler *prof; dvander@3270: dvander@3270: if ((err = handlesys->ReadHandle(hndl, g_ProfilerType, &sec, (void **)&prof)) dvander@3270: != HandleError_None) dvander@3270: { dvander@3270: return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err); dvander@3270: } dvander@3270: dvander@3270: #if defined PLATFORM_WINDOWS dvander@3270: QueryPerformanceCounter(&prof->start); dvander@3270: #else dvander@3270: gettimeofday(&prof->start, NULL); dvander@3270: #endif dvander@3270: dvander@3270: prof->started = true; dvander@3270: prof->stopped = false; dvander@3270: dvander@3270: return 1; dvander@3270: } dvander@3270: dvander@3270: static cell_t StopProfiling(IPluginContext *pContext, const cell_t *params) dvander@3270: { dvander@3270: Handle_t hndl = params[1]; dvander@3270: HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent); dvander@3270: HandleError err; dvander@3270: Profiler *prof; dvander@3270: dvander@3270: if ((err = handlesys->ReadHandle(hndl, g_ProfilerType, &sec, (void **)&prof)) dvander@3270: != HandleError_None) dvander@3270: { dvander@3270: return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err); dvander@3270: } dvander@3270: dvander@3270: if (!prof->started) dvander@3270: { dvander@3270: return pContext->ThrowNativeError("Profiler was never started"); dvander@3270: } dvander@3270: dvander@3270: #if defined PLATFORM_WINDOWS dvander@3270: QueryPerformanceCounter(&prof->end); dvander@3270: #else dvander@3270: gettimeofday(&prof->end, NULL); dvander@3270: #endif dvander@3270: dvander@3270: prof->started = false; dvander@3270: prof->stopped = true; dvander@3270: dvander@3270: return 1; dvander@3270: } dvander@3270: dvander@3270: static cell_t GetProfilerTime(IPluginContext *pContext, const cell_t *params) dvander@3270: { dvander@3270: Handle_t hndl = params[1]; dvander@3270: HandleSecurity sec = HandleSecurity(pContext->GetIdentity(), g_pCoreIdent); dvander@3270: HandleError err; dvander@3270: Profiler *prof; dvander@3270: dvander@3270: if ((err = handlesys->ReadHandle(hndl, g_ProfilerType, &sec, (void **)&prof)) dvander@3270: != HandleError_None) dvander@3270: { dvander@3270: return pContext->ThrowNativeError("Invalid Handle %x (error %d)", hndl, err); dvander@3270: } dvander@3270: dvander@3270: if (!prof->stopped) dvander@3270: { dvander@3270: return pContext->ThrowNativeError("Profiler was never stopped"); dvander@3270: } dvander@3270: dvander@3270: float fTime; dvander@3270: dvander@3270: #if defined PLATFORM_WINDOWS dvander@3270: LONGLONG diff = prof->end.QuadPart - prof->start.QuadPart; dvander@3270: double seconds = diff * prof->freq; dvander@3270: fTime = (float)seconds; dvander@3270: #else dvander@3270: int64_t start_us = int64_t(prof->start.tv_sec) * 1000000 + prof->start.tv_usec; dvander@3270: int64_t stop_us = int64_t(prof->end.tv_sec) * 1000000 + prof->end.tv_usec; asherkin@3639: fTime = double(stop_us - start_us) / 1000000.0; dvander@3270: #endif dvander@3270: dvander@3270: return sp_ftoc(fTime); dvander@3270: } dvander@3270: dvander@3270: REGISTER_NATIVES(profilerNatives) dvander@3270: { dvander@3270: {"CreateProfiler", CreateProfiler}, dvander@3270: {"GetProfilerTime", GetProfilerTime}, dvander@3270: {"StartProfiling", StartProfiling}, dvander@3270: {"StopProfiling", StopProfiling}, dvander@3270: {NULL, NULL}, dvander@3270: }; dvander@3270: