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