Nota
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En el ejemplo siguiente se muestra cómo usar eventos para calcular el uso de la CPU para un conjunto de instrucciones. En este ejemplo se supone que el proveedor ajusta el conjunto de instrucciones con un tipo de evento de inicio y un tipo de evento de fin.
//Turns the DEFINE_GUID for EventTraceGuid into a const.
#define INITGUID
#include <windows.h>
#include <stdio.h>
#include <wbemidl.h>
#include <wmistr.h>
#include <evntrace.h>
#define LOGFILE_PATH L"<FULLPATHTOLOGFILE.etl>"
//Remember to use your own GUID. Event class GUID used in the provider.
// {12BF20F2-0B1C-47e8-90B3-13C81C7AFD9A}
static const GUID CpuUsageEvent =
{ 0x12bf20f2, 0xb1c, 0x47e8, { 0x90, 0xb3, 0x13, 0xc8, 0x1c, 0x7a, 0xfd, 0x9a } };
// Used to calculate CPU usage
ULONG g_TimerResolution = 0;
// Used to determine if the session is a private session or kernel session.
// You need to know this when accessing some members of the EVENT_TRACE.Header
// member (for example, KernelTime or UserTime).
BOOL g_bUserMode = FALSE;
//Start time value for the start event.
ULONG g_StartKernelTime = 0;
ULONG g_StartUserTime = 0;
ULONG64 g_StartProcessTime = 0;
void WINAPI ProcessEvent(PEVENT_TRACE pEvent);
void wmain(void)
{
ULONG status = ERROR_SUCCESS;
EVENT_TRACE_LOGFILE trace;
TRACE_LOGFILE_HEADER* pHeader = &trace.LogfileHeader;
TRACEHANDLE hTrace = 0;
// Identify the log file from which you want to consume events
// and the callbacks used to process the events and buffers.
ZeroMemory(&trace, sizeof(EVENT_TRACE_LOGFILE));
trace.LogFileName = (LPWSTR) LOGFILE_PATH;
trace.EventCallback = (PEVENT_CALLBACK) (ProcessEvent);
hTrace = OpenTrace(&trace);
if ((TRACEHANDLE)INVALID_HANDLE_VALUE == hTrace)
{
wprintf(L"OpenTrace failed with %lu\n", GetLastError());
goto cleanup;
}
g_bUserMode = pHeader->LogFileMode & EVENT_TRACE_PRIVATE_LOGGER_MODE;
if (pHeader->TimerResolution > 0)
{
g_TimerResolution = pHeader->TimerResolution / 10000;
}
status = ProcessTrace(&hTrace, 1, 0, 0);
if (status != ERROR_SUCCESS && status != ERROR_CANCELLED)
{
wprintf(L"ProcessTrace failed with %lu\n", status);
goto cleanup;
}
cleanup:
if ((TRACEHANDLE)INVALID_HANDLE_VALUE != hTrace)
{
status = CloseTrace(hTrace);
}
}
VOID WINAPI ProcessEvent(PEVENT_TRACE pEvent)
{
ULONG64 CPUProcessUnits = 0;
ULONG CPUUnits = 0;
double CPUTime = 0;
// Skips the event if it is the event trace header. Log files contain this event
// but real-time sessions do not. The event contains the same information as
// the EVENT_TRACE_LOGFILE.LogfileHeader member that you can access when you open
// the trace.
if (IsEqualGUID(pEvent->Header.Guid, EventTraceGuid) &&
pEvent->Header.Class.Type == EVENT_TRACE_TYPE_INFO)
{
; // Skip this event.
}
else
{
if (IsEqualGUID(CpuUsageEvent, pEvent->Header.Guid))
{
// This example assumes that the start and end events are paired.
// If this is the start event type, retrieve the start time values from the
// event; otherwise, retrieve the end time values from the event.
if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_START)
{
// If the session is a private session, use the ProcessorTime
// value to calculate the CPU time; otherwise, use the
// KernelTime and UserTime values.
if (g_bUserMode) // Private session
{
g_StartProcessTime = pEvent->Header.ProcessorTime;
}
else // Kernel session
{
g_StartKernelTime = pEvent->Header.KernelTime;
g_StartUserTime = pEvent->Header.UserTime;
}
}
else if (pEvent->Header.Class.Type == EVENT_TRACE_TYPE_END)
{
if (g_bUserMode) // Private session
{
// Calculate CPU time units used.
CPUProcessUnits = pEvent->Header.ProcessorTime - g_StartProcessTime;
wprintf(L"CPU time units used, %Lu.\n", CPUProcessUnits);
// Processor time is in CPU ticks. Convert ticks to seconds.
// 1000000000 = nanoseconds in one second.
CPUTime = (double)(CPUProcessUnits) / 1000000000;
wprintf(L"Process CPU usage in seconds, %Lf.\n", CPUTime);
}
else // Kernel session
{
// Calculate the kernel mode CPU time units used for the set of instructions.
CPUUnits = pEvent->Header.KernelTime - g_StartKernelTime;
wprintf(L"CPU time units used (kernel), %d.\n", CPUUnits);
// Calculate the kernel mode CPU time in seconds for the set of instructions.
// 100 = 100 nanoseconds, 1000000000 = nanoseconds in one second
CPUTime = (double)(g_TimerResolution * CPUUnits * 100) / 1000000000;
wprintf(L"Kernel mode CPU usage in seconds, %Lf.\n", CPUTime);
// Calculate user mode CPU time units used for the set of instructions.
CPUUnits = pEvent->Header.UserTime - g_StartUserTime;
wprintf(L"\nCPU time units used (user), %d.\n", CPUUnits);
// Calculate the user mode CPU time in seconds for the set of instructions.
// 100 = 100 nanoseconds, 1000000000 = nanoseconds in one second
CPUTime = (double)(g_TimerResolution * CPUUnits * 100) / 1000000000;
wprintf(L"User mode CPU usage in seconds, %Lf.\n", CPUTime);
}
}
}
}
}