Counting context switches for a specific process in Windows

What I would like to do is write a small program that constantly lives, counts the number of context switches that a certain process experiences in a fairly small unit of time. I have observed this functionality in the Process Explorer software, so I know that it is definitely possible.

Unfortunately, I have very little information on how to start coding this and still have not been able to find useful code snippets on the Internet. Thus, a small working example that implements a context context context counter for each process and per unit of time would be very useful for me.

0
source share
3 answers

Here's one way to do this - this will print the number of context switches used by notepad thread 0 (you can replace any process and thread number you want in the CounterPathBuffer initialization) every second:

#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; } 

Most of the code is taken from this source: msdn.microsoft.com/en-us/library/aa371886%28v=vs.85%29.aspx . I would like to reduce the time between successive checks of context switches (to do this in less than a second). If anyone has any ideas on how to do this, that would be great.

+1
source

A small search on the Internet, and I found this thing called " Performance Counters ", you can either provide the counter data, or use the counter data using This. In your case, I believe you want to read data from performance counters.

You can use performance data using either the registry interface or the PDH interface. The PDH interface is easier to use than the registry interface, and is recommended for most performance data collection tasks. The PDH interface is essentially an abstraction of the higher level of functionality provided by the registry interface.

Here is another article from Microsoft on Monitoring Context Switches .

0
source

ETW (Event Tracing for Windows) will give you much deeper information about context switches if you want. The code is likely to be significantly more complex than accessing performance counters.

Source links: Windows 7 major events in Windows 7 and the Windows Productivity Toolkit Technical Reference

Searches: "ETW Context Switches", "xperf"

0
source

All Articles