Bagikan melalui


Mengakses Data Kinerja pada C++

API berkinerja tinggi WMI adalah serangkaian antarmuka yang mendapatkan data dari Kelas Penghitung Kinerja . Antarmuka ini memerlukan penggunaan objek penyegar untuk meningkatkan laju pengambilan sampel. Untuk informasi selengkapnya tentang menggunakan objek penyegaran dalam pembuatan skrip, lihat Mengakses Data Kinerja dalam Skrip dan Tugas WMI: Pemantauan Kinerja.

Bagian berikut dibahas dalam topik ini:

Memperbarui Data Kinerja

Objek penyegar meningkatkan kinerja penyedia data dan klien dengan mengambil data tanpa melewati batas proses. Jika klien dan server terletak di komputer yang sama, penyegaran memuat penyedia berkinerja tinggi dalam proses ke klien, dan menyalin data langsung dari objek penyedia ke objek klien. Jika klien dan server berada di komputer yang berbeda, penyegaran meningkatkan performa dengan penyimpanan sementara objek di komputer jarak jauh, dan mengirimkan data minimal ke klien.

Sebagai penyegaran tambahan:

  • Secara otomatis menyambungkan ulang klien ke layanan WMI jarak jauh ketika terjadi kesalahan jaringan, atau komputer jarak jauh dimulai ulang.

    Sebagai pengaturan awal, penyegaran mencoba menyambungkan kembali aplikasi Anda ke penyedia berkinerja tinggi yang relevan saat koneksi jarak jauh antara kedua komputer gagal. Untuk mencegah koneksi ulang, berikan bendera WBEM_FLAG_REFRESH_NO_AUTO_RECONNECT dalam panggilan metode Refresh. Klien scripting harus menyetel properti SWbemRefresher.AutoReconnect ke FALSE.

  • Memuat beberapa objek dan enumerator yang disediakan oleh penyedia yang sama atau berbeda.

    Memungkinkan Anda menambahkan beberapa objek, enumerator, atau keduanya ke penyegaran.

  • Menghitung objek.

    Seperti penyedia lain, penyedia berkinerja tinggi dapat menghitung objek.

Setelah Anda selesai menulis aplikasi klien berkinerja tinggi, Anda mungkin ingin mempercepat waktu respons. Karena antarmuka IWbemObjectAccess dioptimalkan untuk kecepatan, antarmuka ini tidak intrinsik aman terhadap lintas thread. Oleh karena itu, selama operasi refresh, jangan akses objek atau enumerasi yang dapat di-refresh. Untuk melindungi objek antar-utas selama panggilan metode IWbemObjectAccess, gunakan metode IWbemObjectAccess::Lock dan Unlock. Untuk meningkatkan kinerja, sinkronkan benang Anda sehingga Anda tidak perlu mengunci setiap benang secara individual. Mengurangi utas dan menyinkronkan grup objek untuk operasi refresh memberikan performa keseluruhan terbaik.

Menambahkan Enumerator ke Penyegar WMI

Baik jumlah instans maupun data di setiap instans diperbarui dengan menambahkan enumerator ke penyegar sehingga setiap pemanggilan ke IWbemRefresher::Refresh menghasilkan enumerasi yang lengkap.

Contoh kode C++ berikut memerlukan referensi berikut dan pernyataan #include untuk dikompilasi dengan benar.

#define _WIN32_DCOM

#include <iostream>
using namespace std;
#include <Wbemidl.h>
#pragma comment(lib, "wbemuuid.lib")

Prosedur berikut menggambarkan cara menambahkan enumerator ke pemutakhiran.

Untuk menambahkan enumerator ke pemutakhiran

  1. Panggil metode IWbemConfigureRefresher::AddEnum menggunakan jalur ke objek yang dapat di-refresh dan antarmukaIWbemServices.

    Penyegar mengembalikan penunjuk ke antarmuka IWbemHiPerfEnum. Anda dapat menggunakan antarmuka IWbemHiPerfEnum untuk mengakses objek dalam enumerasi.

    IWbemHiPerfEnum* pEnum = NULL;
    long lID;
    IWbemConfigureRefresher* pConfig;
    IWbemServices* pNameSpace;
    
    // Add an enumerator to the refresher.
    if (FAILED (hr = pConfig->AddEnum(
        pNameSpace, 
        L"Win32_PerfRawData_PerfProc_Process", 
        0, 
        NULL,
        &pEnum, 
        &lID)))
    {
        goto CLEANUP;
    }
    pConfig->Release();
    pConfig = NULL;
    
  2. Buat perulangan yang melakukan tindakan berikut:

Contoh

Contoh kode C++ berikut menjumlahkan kelas berkinerja tinggi, di mana klien mengambil handle properti dari objek pertama, dan menggunakan kembali handle tersebut untuk sisa operasi pembaruan. Setiap panggilan ke metode Refresh memperbarui jumlah instans dan data instans.

#define _WIN32_DCOM

#include <iostream>
using namespace std;
#include <Wbemidl.h>

#pragma comment(lib, "wbemuuid.lib")

int __cdecl wmain(int argc, wchar_t* argv[])
{
    // To add error checking,
    // check returned HRESULT below where collected.
    HRESULT                 hr = S_OK;
    IWbemRefresher          *pRefresher = NULL;
    IWbemConfigureRefresher *pConfig = NULL;
    IWbemHiPerfEnum         *pEnum = NULL;
    IWbemServices           *pNameSpace = NULL;
    IWbemLocator            *pWbemLocator = NULL;
    IWbemObjectAccess       **apEnumAccess = NULL;
    BSTR                    bstrNameSpace = NULL;
    long                    lID = 0;
    long                    lVirtualBytesHandle = 0;
    long                    lIDProcessHandle = 0;
    DWORD                   dwVirtualBytes = 0;
    DWORD                   dwProcessId = 0;
    DWORD                   dwNumObjects = 0;
    DWORD                   dwNumReturned = 0;
    DWORD                   dwIDProcess = 0;
    DWORD                   i=0;
    int                     x=0;

    if (FAILED (hr = CoInitializeEx(NULL,COINIT_MULTITHREADED)))
    {
        goto CLEANUP;
    }

    if (FAILED (hr = CoInitializeSecurity(
        NULL,
        -1,
        NULL,
        NULL,
        RPC_C_AUTHN_LEVEL_NONE,
        RPC_C_IMP_LEVEL_IMPERSONATE,
        NULL, EOAC_NONE, 0)))
    {
        goto CLEANUP;
    }

    if (FAILED (hr = CoCreateInstance(
        CLSID_WbemLocator, 
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_IWbemLocator,
        (void**) &pWbemLocator)))
    {
        goto CLEANUP;
    }

    // Connect to the desired namespace.
    bstrNameSpace = SysAllocString(L"\\\\.\\root\\cimv2");
    if (NULL == bstrNameSpace)
    {
        hr = E_OUTOFMEMORY;
        goto CLEANUP;
    }
    if (FAILED (hr = pWbemLocator->ConnectServer(
        bstrNameSpace,
        NULL, // User name
        NULL, // Password
        NULL, // Locale
        0L,   // Security flags
        NULL, // Authority
        NULL, // Wbem context
        &pNameSpace)))
    {
        goto CLEANUP;
    }
    pWbemLocator->Release();
    pWbemLocator=NULL;
    SysFreeString(bstrNameSpace);
    bstrNameSpace = NULL;

    if (FAILED (hr = CoCreateInstance(
        CLSID_WbemRefresher,
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_IWbemRefresher, 
        (void**) &pRefresher)))
    {
        goto CLEANUP;
    }

    if (FAILED (hr = pRefresher->QueryInterface(
        IID_IWbemConfigureRefresher,
        (void **)&pConfig)))
    {
        goto CLEANUP;
    }

    // Add an enumerator to the refresher.
    if (FAILED (hr = pConfig->AddEnum(
        pNameSpace, 
        L"Win32_PerfRawData_PerfProc_Process", 
        0, 
        NULL, 
        &pEnum, 
        &lID)))
    {
        goto CLEANUP;
    }
    pConfig->Release();
    pConfig = NULL;

    // Get a property handle for the VirtualBytes property.

    // Refresh the object ten times and retrieve the value.
    for(x = 0; x < 10; x++)
    {
        dwNumReturned = 0;
        dwIDProcess = 0;
        dwNumObjects = 0;

        if (FAILED (hr =pRefresher->Refresh(0L)))
        {
            goto CLEANUP;
        }

        hr = pEnum->GetObjects(0L, 
            dwNumObjects, 
            apEnumAccess, 
            &dwNumReturned);
        // If the buffer was not big enough,
        // allocate a bigger buffer and retry.
        if (hr == WBEM_E_BUFFER_TOO_SMALL 
            && dwNumReturned > dwNumObjects)
        {
            apEnumAccess = new IWbemObjectAccess*[dwNumReturned];
            if (NULL == apEnumAccess)
            {
                hr = E_OUTOFMEMORY;
                goto CLEANUP;
            }
            SecureZeroMemory(apEnumAccess,
                dwNumReturned*sizeof(IWbemObjectAccess*));
            dwNumObjects = dwNumReturned;

            if (FAILED (hr = pEnum->GetObjects(0L, 
                dwNumObjects, 
                apEnumAccess, 
                &dwNumReturned)))
            {
                goto CLEANUP;
            }
        }
        else
        {
            if (hr == WBEM_S_NO_ERROR)
            {
                hr = WBEM_E_NOT_FOUND;
                goto CLEANUP;
            }
        }

        // First time through, get the handles.
        if (0 == x)
        {
            CIMTYPE VirtualBytesType;
            CIMTYPE ProcessHandleType;
            if (FAILED (hr = apEnumAccess[0]->GetPropertyHandle(
                L"VirtualBytes",
                &VirtualBytesType,
                &lVirtualBytesHandle)))
            {
                goto CLEANUP;
            }
            if (FAILED (hr = apEnumAccess[0]->GetPropertyHandle(
                L"IDProcess",
                &ProcessHandleType,
                &lIDProcessHandle)))
            {
                goto CLEANUP;
            }
        }
           
        for (i = 0; i < dwNumReturned; i++)
        {
            if (FAILED (hr = apEnumAccess[i]->ReadDWORD(
                lVirtualBytesHandle,
                &dwVirtualBytes)))
            {
                goto CLEANUP;
            }
            if (FAILED (hr = apEnumAccess[i]->ReadDWORD(
                lIDProcessHandle,
                &dwIDProcess)))
            {
                goto CLEANUP;
            }

            wprintf(L"Process ID %lu is using %lu bytes\n",
                dwIDProcess, dwVirtualBytes);

            // Done with the object
            apEnumAccess[i]->Release();
            apEnumAccess[i] = NULL;
        }

        if (NULL != apEnumAccess)
        {
            delete [] apEnumAccess;
            apEnumAccess = NULL;
        }

       // Sleep for a second.
       Sleep(1000);
    }
    // exit loop here
    CLEANUP:

    if (NULL != bstrNameSpace)
    {
        SysFreeString(bstrNameSpace);
    }

    if (NULL != apEnumAccess)
    {
        for (i = 0; i < dwNumReturned; i++)
        {
            if (apEnumAccess[i] != NULL)
            {
                apEnumAccess[i]->Release();
                apEnumAccess[i] = NULL;
            }
        }
        delete [] apEnumAccess;
    }
    if (NULL != pWbemLocator)
    {
        pWbemLocator->Release();
    }
    if (NULL != pNameSpace)
    {
        pNameSpace->Release();
    }
    if (NULL != pEnum)
    {
        pEnum->Release();
    }
    if (NULL != pConfig)
    {
        pConfig->Release();
    }
    if (NULL != pRefresher)
    {
        pRefresher->Release();
    }

    CoUninitialize();

    if (FAILED (hr))
    {
        wprintf (L"Error status=%08x\n",hr);
    }

    return 1;
}

Kelas Penghitung Kinerja

Mengakses Data Performa dalam Skrip

Menyegarkan Data WMI dalam Skrip

Tugas WMI: Pemantauan Performa

Pemantauan Data Kinerja

Kualifikasi Properti untuk Kelas Penghitung Kinerja Terformat

jenis penghitung kinerja WMI

Wmiadap.exe

QueryPerformanceCounter