Подсчет переключателей контекста для конкретного процесса в Windows

Что я хотел бы сделать, так это написать небольшую программу, которая постоянно работает, подсчитывает количество переключений контекста, которое происходит в конкретном процессе за достаточно малую единицу времени. Я наблюдал эту функциональность в программном обеспечении «Process Explorer», поэтому я знаю, что это определенно возможно.

К сожалению, я очень мало представляю, как начать это кодировать, и до сих пор не смог найти в Интернете никаких полезных фрагментов кода. Таким образом, небольшой рабочий пример, реализующий подсчет переключений контекста в реальном времени и за единицу времени, был бы для меня чрезвычайно полезным.

0

Решение

Вот один из способов сделать это — это будет печатать количество переключений контекста, используемых потоком 0 блокнота (вы можете заменить любой процесс и номер потока, который вы хотите при инициализации CounterPathBuffer) каждую секунду:

#include "stdafx.h"#include <iostream>
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <pdh.h>
#include <pdhmsg.h>

#pragma comment(lib, "pdh.lib")
using namespace std;
CONST ULONG SAMPLE_INTERVAL_MS    = 1000;
CONST PWSTR BROWSE_DIALOG_CAPTION = L"Select a counter to monitor.";

void wmain(void)
{
PDH_STATUS Status;
HQUERY Query = NULL;
HCOUNTER Counter;
PDH_FMT_COUNTERVALUE DisplayValue;
DWORD CounterType;
SYSTEMTIME SampleTime;
PDH_BROWSE_DLG_CONFIG BrowseDlgData;
WCHAR CounterPathBuffer[PDH_MAX_COUNTER_PATH] = L"\\\\ComputerNameGoesHere\\Thread(notepad/0)\\Context Switches/sec";//
// Create a query.
//

Status = PdhOpenQuery(NULL, NULL, &Query);
if (Status != ERROR_SUCCESS)
{
wprintf(L"\nPdhOpenQuery failed with status 0x%x.", Status);
goto Cleanup;
}

//
// Initialize the browser dialog window settings.
//ZeroMemory(&BrowseDlgData, sizeof(PDH_BROWSE_DLG_CONFIG));

BrowseDlgData.bIncludeInstanceIndex = FALSE;
BrowseDlgData.bSingleCounterPerAdd = TRUE;
BrowseDlgData.bSingleCounterPerDialog = TRUE;
BrowseDlgData.bLocalCountersOnly = FALSE;
BrowseDlgData.bWildCardInstances = TRUE;
BrowseDlgData.bHideDetailBox = TRUE;
BrowseDlgData.bInitializePath = FALSE;
BrowseDlgData.bDisableMachineSelection = FALSE;
BrowseDlgData.bIncludeCostlyObjects = FALSE;
BrowseDlgData.bShowObjectBrowser = FALSE;
BrowseDlgData.hWndOwner = NULL;
BrowseDlgData.szReturnPathBuffer = CounterPathBuffer;
BrowseDlgData.cchReturnPathLength = PDH_MAX_COUNTER_PATH;
BrowseDlgData.pCallBack = NULL;
BrowseDlgData.dwCallBackArg = 0;
BrowseDlgData.CallBackStatus = ERROR_SUCCESS;
BrowseDlgData.dwDefaultDetailLevel = PERF_DETAIL_WIZARD;
BrowseDlgData.szDialogBoxCaption = BROWSE_DIALOG_CAPTION;

//
// Add the selected counter to the query.
//Status = PdhAddCounter(Query, CounterPathBuffer, 0, &Counter);
if (Status != ERROR_SUCCESS)
{
wprintf(L"\nPdhAddCounter failed with status 0x%x.", Status);
goto Cleanup;
}

//
// Most counters require two sample values to display a formatted value.
// PDH stores the current sample value and the previously collected
// sample value. This call retrieves the first value that will be used
// by PdhGetFormattedCounterValue in the first iteration of the loop
// Note that this value is lost if the counter does not require two
// values to compute a displayable value.
//

Status = PdhCollectQueryData(Query);
if (Status != ERROR_SUCCESS)
{
wprintf(L"\nPdhCollectQueryData failed with 0x%x.\n", Status);
goto Cleanup;
}

//
// Print counter values until a key is pressed.
//

while (!_kbhit())
{
Sleep(SAMPLE_INTERVAL_MS);

GetLocalTime(&SampleTime);

Status = PdhCollectQueryData(Query);
if (Status != ERROR_SUCCESS)
{
wprintf(L"\nPdhCollectQueryData failed with status 0x%x.", Status);
}

wprintf(L"\n\"%2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d.%3.3d\"",
SampleTime.wMonth,
SampleTime.wDay,
SampleTime.wYear,
SampleTime.wHour,
SampleTime.wMinute,
SampleTime.wSecond,
SampleTime.wMilliseconds);

//
// Compute a displayable value for the counter.
//

Status = PdhGetFormattedCounterValue(Counter,
PDH_FMT_DOUBLE,
&CounterType,
&DisplayValue);
if (Status != ERROR_SUCCESS)
{
wprintf(L"\nPdhGetFormattedCounterValue failed with status 0x%x.", Status);
goto Cleanup;
}wprintf(L",\"%.20g\"", DisplayValue.doubleValue);
}

Cleanup:

//
// Close the query.
//

if (Query)
{
PdhCloseQuery(Query);
}

int x;
cin >>x;
}

Большая часть кода из этого источника: msdn.microsoft.com/en-us/library/aa371886%28v=vs.85%29.aspx. Я хотел бы сократить количество времени между последовательными проверками переключений контекста (сделать его менее секунды). Если у кого-то есть идеи, как это сделать, это было бы здорово.

1

Другие решения

Немного поиска в интернете и я нашел эту вещь под названием «Счетчики производительности«, вы можете либо предоставить данные счетчика, либо использовать данные счетчика вместе с ним. В вашем случае, я полагаю, вы хотите прочитать данные из счетчиков производительности.

Вы можете использовать данные о производительности, используя интерфейс реестра или интерфейс PDH. Интерфейс PDH проще в использовании, чем интерфейс реестра, и рекомендуется для большинства задач сбора данных о производительности. Интерфейс PDH — это абстракция более высокого уровня функциональности, которую обеспечивает интерфейс реестра.

Вот еще одна статья от Microsoft на Мониторинг переключений контекста.

0

ETW (Event Tracing for Windows) даст вам гораздо более глубокую информацию о переключениях контекста, если хотите. Код, вероятно, будет значительно сложнее, чем доступ к счетчикам производительности.

Начальные ссылки: Основные события ОС в Windows 7 а также Технический справочник по Windows Performance Toolkit

Поисковые термины: «переключатели контекста ETW», «xperf»

0
По вопросам рекламы ammmcru@yandex.ru
Adblock
detector