1

私がやりたいのは、特定のプロセスが十分に短い時間単位で経験するコンテキストスイッチの数を継続的にカウントする小さなプログラムを作成することです。私はソフトウェア「ProcessExplorer」内でこの機能を観察したので、それが確実に可能であることを知っています。

残念ながら、これをコーディングし始める方法についてはほとんどわかりません。これまでのところ、役立つコードスニペットをオンラインで見つけることができませんでした。したがって、プロセスごとおよび単位時間ごとのライブコンテキストスイッチカウントを実装する小さな実用的な例は、私にとって非常に役立ちます。

4

3 に答える 3

1

これを行う1つの方法は次のとおりです。これにより、メモ帳のスレッド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秒未満にする)。誰かがこれを行う方法について何かアイデアを持っているなら、それは素晴らしいことです。

于 2012-09-29T15:22:03.783 に答える
0

インターネットで少し調べてみると、「パフォーマンスカウンター」と呼ばれるものが見つかりました。カウンターデータを提供することも、カウンターデータを使用することもできます。あなたの場合、パフォーマンスカウンターからデータを読み取りたいと思います。

レジストリインターフェイスまたはPDHインターフェイスのいずれかを使用してパフォーマンスデータを使用できます。PDHインターフェイスは、レジストリインターフェイスよりも使いやすく、ほとんどのパフォーマンスデータ収集タスクに推奨されます。PDHインターフェイスは、基本的に、レジストリインターフェイスが提供する機能の高レベルの抽象化です。

これは、コンテキストスイッチの監視に関するMicrosoftの別の記事です。

于 2012-09-29T03:43:31.390 に答える
0

ETW(Event Tracing for Windows)は、必要に応じて、コンテキストスイッチに関するより詳細な情報を提供します。コードは、パフォーマンスカウンターへのアクセスよりも大幅に複雑になる可能性があります。

初期リンク: Windows7およびWindowsPerformanceToolkitテクニカルリファレンスのコアOSイベント

検索用語:「ETWコンテキストスイッチ」、「xperf」

于 2012-10-04T03:43:44.503 に答える