/** * * Retrieve GDI resource usage for process. * * @param Nil * @return bool - Return status. * @exception Nil * @see Nil * @since 1.0 */ bool Process::ExtractGDIInfo() { // Check whether process handle is valid if( !m_ahmProcess.IsValid() ) { return false; } // Get resource usage count m_dwGDIObjs = GetGuiResources( m_ahmProcess, GR_GDIOBJECTS ); m_dwUserObjs = GetGuiResources( m_ahmProcess, GR_USEROBJECTS ); return GetLastError() == NO_ERROR; }
// Returns whether we should, at this time, use image surfaces instead of // optimized platform-specific surfaces. static bool ShouldUseImageSurfaces() { #if defined(USE_WIN_SURFACE) static const DWORD kGDIObjectsHighWaterMark = 7000; if (gfxWindowsPlatform::GetPlatform()->GetRenderMode() == gfxWindowsPlatform::RENDER_DIRECT2D) { return PR_TRUE; } // at 7000 GDI objects, stop allocating normal images to make sure // we never hit the 10k hard limit. // GetCurrentProcess() just returns (HANDLE)-1, it's inlined afaik DWORD count = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS); if (count == 0 || count > kGDIObjectsHighWaterMark) { // either something's broken (count == 0), // or we hit our high water mark; disable // image allocations for a bit. return PR_TRUE; } #endif return PR_FALSE; }
BOOL isGuiApp() { DWORD mypid; HANDLE myprocess; mypid = GetCurrentProcessId(); myprocess = OpenProcess( PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, mypid); return GetGuiResources(myprocess, 1) > 0; }
void CCrashHandler::CollectMiscCrashInfo() { // Get crash time Utility::GetSystemTimeUTC(m_sCrashTime); HANDLE hCurProcess = GetCurrentProcess(); // Determine the period of time the process is working. SYSTEMTIME CurTime; GetSystemTime(&CurTime); ULONG64 uCurTime = Utility::SystemTimeToULONG64(CurTime); ULONG64 uStartTime = Utility::SystemTimeToULONG64(m_AppStartTime); // Check that the application works for at least one minute before crash. // This might help to avoid cyclic error report generation when the applciation // crashes on startup. double dDiffTime = (double)(uCurTime-uStartTime)*10E-08; if(dDiffTime<60) { m_bAppRestart = FALSE; // Disable restart. } // Get number of GUI resources in use m_dwGuiResources = GetGuiResources(hCurProcess, GR_GDIOBJECTS); // Determine if GetProcessHandleCount function available typedef BOOL (WINAPI *LPGETPROCESSHANDLECOUNT)(HANDLE, PDWORD); HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll")); LPGETPROCESSHANDLECOUNT pfnGetProcessHandleCount = (LPGETPROCESSHANDLECOUNT)GetProcAddress(hKernel32, "GetProcessHandleCount"); if(pfnGetProcessHandleCount!=NULL) { // Get count of opened handles DWORD dwHandleCount = 0; BOOL bGetHandleCount = pfnGetProcessHandleCount(hCurProcess, &dwHandleCount); if(bGetHandleCount) m_dwProcessHandleCount = dwHandleCount; else m_dwProcessHandleCount = 0; } // Get memory usage info PROCESS_MEMORY_COUNTERS meminfo; BOOL bGetMemInfo = GetProcessMemoryInfo(hCurProcess, &meminfo, sizeof(PROCESS_MEMORY_COUNTERS)); if(bGetMemInfo) { CString sMemUsage; #ifdef _WIN64 sMemUsage.Format(_T("%I64u"), meminfo.WorkingSetSize/1024); #else sMemUsage.Format(_T("%lu"), meminfo.WorkingSetSize/1024); #endif m_sMemUsage = sMemUsage; } // Get cursor position GetCursorPos(&m_ptCursorPos); }
void CCrashHandler::CollectMiscCrashInfo() { // Get crash time Utility::GetSystemTimeUTC(m_sCrashTime); // Get number of GUI resources in use HANDLE hCurProcess = GetCurrentProcess(); m_dwGuiResources = GetGuiResources(hCurProcess, GR_GDIOBJECTS); // Determine if GetProcessHandleCount function available typedef BOOL (WINAPI *LPGETPROCESSHANDLECOUNT)(HANDLE, PDWORD); HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll")); LPGETPROCESSHANDLECOUNT pfnGetProcessHandleCount = (LPGETPROCESSHANDLECOUNT)GetProcAddress(hKernel32, "GetProcessHandleCount"); if(pfnGetProcessHandleCount!=NULL) { // Get count of opened handles DWORD dwHandleCount = 0; BOOL bGetHandleCount = pfnGetProcessHandleCount(hCurProcess, &dwHandleCount); if(bGetHandleCount) m_dwProcessHandleCount = dwHandleCount; else m_dwProcessHandleCount = 0; } // Get memory usage info PROCESS_MEMORY_COUNTERS meminfo; BOOL bGetMemInfo = GetProcessMemoryInfo(hCurProcess, &meminfo, sizeof(PROCESS_MEMORY_COUNTERS)); if(bGetMemInfo) { CString sMemUsage; #ifdef _WIN64 sMemUsage.Format(_T("%I64u"), meminfo.WorkingSetSize/1024); #else sMemUsage.Format(_T("%lu"), meminfo.WorkingSetSize/1024); #endif m_sMemUsage = sMemUsage; } // Get cursor position GetCursorPos(&m_ptCursorPos); }
// 使进程崩溃. 当位图分配失败时调用, 函数尝试确定失败的原因, 并在适当的地方触发 // 崩溃. 这样我们可以更加清楚导致崩溃的原因. 函数需要传入位图的宽高, 这样可以试 // 着创建位图定位错误. // // 注意在沙盒渲染器中, 函数调用GetProcessMemoryInfo()会导致崩溃, 因为此时会加载 // load psapi.dll, 这么做是正确的, 但这种崩溃有可能让你摸不着头脑. void CrashForBitmapAllocationFailure(int w, int h) { // 存储扩展的错误信息到一个调试时容易找到的地方. struct { unsigned int last_error; unsigned int diag_error; } extended_error_info; extended_error_info.last_error = GetLastError(); extended_error_info.diag_error = 0; // 如果位图太大, 有可能分配失败. // 使用64M像素=256MB, 每个像素4字节来检查. const __int64 kGinormousBitmapPxl = 64000000; CHECK(static_cast<__int64>(w) * static_cast<__int64>(h) < kGinormousBitmapPxl); // 每个进程GDI对象的上限是10K. 如果接近这个值, 很可能出现问题. const unsigned int kLotsOfGDIObjects = 9990; unsigned int num_gdi_objects = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS); if(num_gdi_objects == 0) { extended_error_info.diag_error = GetLastError(); CHECK(0); } CHECK(num_gdi_objects < kLotsOfGDIObjects); // 如果过度使用虚拟地址空间, 创建位图需要的内存可能不足. const SIZE_T kLotsOfMem = 1500000000; // 1.5GB. PROCESS_MEMORY_COUNTERS pmc; if(!GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) { extended_error_info.diag_error = GetLastError(); CHECK(0); } CHECK(pmc.PagefileUsage < kLotsOfMem); // 其它的问题全部在这里崩溃. CHECK(0); }
PRBool nsThebesImage::ShouldUseImageSurfaces() { #ifdef XP_WIN static const DWORD kGDIObjectsHighWaterMark = 7000; // at 7000 GDI objects, stop allocating normal images to make sure // we never hit the 10k hard limit. // GetCurrentProcess() just returns (HANDLE)-1, it's inlined afaik DWORD count = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS); if (count == 0 || count > kGDIObjectsHighWaterMark) { // either something's broken (count == 0), // or we hit our high water mark; disable // image allocations for a bit. return PR_TRUE; } #endif return PR_FALSE; }
void CCrashInfoReader::CollectMiscCrashInfo(CErrorReportInfo& eri) { // Get crash time Utility::GetSystemTimeUTC(eri.m_sSystemTimeUTC); // Open parent process handle HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, m_dwProcessId); if(hProcess!=NULL) { SIZE_T uBytesRead = 0; BYTE buff[1024]; memset(&buff, 0, 1024); // Read exception information from process memory if(m_pExInfo!=NULL) { if(ReadProcessMemory(hProcess, m_pExInfo, &buff, sizeof(EXCEPTION_POINTERS), &uBytesRead) && uBytesRead==sizeof(EXCEPTION_POINTERS)) { EXCEPTION_POINTERS* pExcPtrs = (EXCEPTION_POINTERS*)buff; if(pExcPtrs->ExceptionRecord!=NULL) { DWORD64 dwExcRecordAddr = (DWORD64)pExcPtrs->ExceptionRecord; if(ReadProcessMemory(hProcess, (LPCVOID)dwExcRecordAddr, &buff, sizeof(EXCEPTION_RECORD), &uBytesRead) && uBytesRead==sizeof(EXCEPTION_RECORD)) { EXCEPTION_RECORD* pExcRec = (EXCEPTION_RECORD*)buff; eri.m_dwExceptionAddress = (DWORD64)pExcRec->ExceptionAddress; } } } } else eri.m_dwExceptionAddress = 0; // Get number of GUI resources in use eri.m_dwGuiResources = GetGuiResources(hProcess, GR_GDIOBJECTS); // Determine if GetProcessHandleCount function available typedef BOOL (WINAPI *LPGETPROCESSHANDLECOUNT)(HANDLE, PDWORD); HMODULE hKernel32 = LoadLibrary(_T("kernel32.dll")); if(hKernel32!=NULL) { LPGETPROCESSHANDLECOUNT pfnGetProcessHandleCount = (LPGETPROCESSHANDLECOUNT)GetProcAddress(hKernel32, "GetProcessHandleCount"); if(pfnGetProcessHandleCount!=NULL) { // Get count of opened handles DWORD dwHandleCount = 0; BOOL bGetHandleCount = pfnGetProcessHandleCount(hProcess, &dwHandleCount); if(bGetHandleCount) eri.m_dwProcessHandleCount = dwHandleCount; else eri.m_dwProcessHandleCount = 0; } FreeLibrary(hKernel32); hKernel32=NULL; } // Get memory usage info PROCESS_MEMORY_COUNTERS meminfo; BOOL bGetMemInfo = GetProcessMemoryInfo(hProcess, &meminfo, sizeof(PROCESS_MEMORY_COUNTERS)); if(bGetMemInfo) { CString sMemUsage; #ifdef _WIN64 sMemUsage.Format(_T("%I64u"), meminfo.WorkingSetSize/1024); #else sMemUsage.Format(_T("%lu"), meminfo.WorkingSetSize/1024); #endif eri.m_sMemUsage = sMemUsage; } // Determine the period of time the process is working. FILETIME CreationTime, ExitTime, KernelTime, UserTime; /*BOOL bGetTimes = */GetProcessTimes(hProcess, &CreationTime, &ExitTime, &KernelTime, &UserTime); /*ATLASSERT(bGetTimes);*/ SYSTEMTIME AppStartTime; FileTimeToSystemTime(&CreationTime, &AppStartTime); SYSTEMTIME CurTime; GetSystemTime(&CurTime); ULONG64 uCurTime = Utility::SystemTimeToULONG64(CurTime); ULONG64 uStartTime = Utility::SystemTimeToULONG64(AppStartTime); // Check that the application works for at least one minute before crash. // This might help to avoid cyclic error report generation when the applciation // crashes on startup. double dDiffTime = (double)(uCurTime-uStartTime)*10E-08; if(dDiffTime<60) { m_bAppRestart = FALSE; // Disable restart. } } // Get operating system friendly name from registry. Utility::GetOSFriendlyName(eri.m_sOSName); // Determine if Windows is 64-bit. eri.m_bOSIs64Bit = Utility::IsOS64Bit(); // Get geographic location. Utility::GetGeoLocation(eri.m_sGeoLocation); }
VOID PhpUpdateProcessStatistics( _In_ HWND hwndDlg, _In_ PPH_PROCESS_ITEM ProcessItem, _In_ PPH_STATISTICS_CONTEXT Context ) { WCHAR timeSpan[PH_TIMESPAN_STR_LEN_1]; SetDlgItemInt(hwndDlg, IDC_ZPRIORITY_V, ProcessItem->BasePriority, TRUE); // priority PhPrintTimeSpan(timeSpan, ProcessItem->KernelTime.QuadPart, PH_TIMESPAN_HMSM); // kernel time SetDlgItemText(hwndDlg, IDC_ZKERNELTIME_V, timeSpan); PhPrintTimeSpan(timeSpan, ProcessItem->UserTime.QuadPart, PH_TIMESPAN_HMSM); // user time SetDlgItemText(hwndDlg, IDC_ZUSERTIME_V, timeSpan); PhPrintTimeSpan(timeSpan, ProcessItem->KernelTime.QuadPart + ProcessItem->UserTime.QuadPart, PH_TIMESPAN_HMSM); // total time SetDlgItemText(hwndDlg, IDC_ZTOTALTIME_V, timeSpan); SetDlgItemText(hwndDlg, IDC_ZPRIVATEBYTES_V, PhaFormatSize(ProcessItem->VmCounters.PagefileUsage, -1)->Buffer); // private bytes (same as PrivateUsage) SetDlgItemText(hwndDlg, IDC_ZPEAKPRIVATEBYTES_V, PhaFormatSize(ProcessItem->VmCounters.PeakPagefileUsage, -1)->Buffer); // peak private bytes SetDlgItemText(hwndDlg, IDC_ZVIRTUALSIZE_V, PhaFormatSize(ProcessItem->VmCounters.VirtualSize, -1)->Buffer); // virtual size SetDlgItemText(hwndDlg, IDC_ZPEAKVIRTUALSIZE_V, PhaFormatSize(ProcessItem->VmCounters.PeakVirtualSize, -1)->Buffer); // peak virtual size SetDlgItemText(hwndDlg, IDC_ZPAGEFAULTS_V, PhaFormatUInt64(ProcessItem->VmCounters.PageFaultCount, TRUE)->Buffer); // page faults SetDlgItemText(hwndDlg, IDC_ZWORKINGSET_V, PhaFormatSize(ProcessItem->VmCounters.WorkingSetSize, -1)->Buffer); // working set SetDlgItemText(hwndDlg, IDC_ZPEAKWORKINGSET_V, PhaFormatSize(ProcessItem->VmCounters.PeakWorkingSetSize, -1)->Buffer); // peak working set SetDlgItemText(hwndDlg, IDC_ZIOREADS_V, PhaFormatUInt64(ProcessItem->IoCounters.ReadOperationCount, TRUE)->Buffer); // reads SetDlgItemText(hwndDlg, IDC_ZIOREADBYTES_V, PhaFormatSize(ProcessItem->IoCounters.ReadTransferCount, -1)->Buffer); // read bytes SetDlgItemText(hwndDlg, IDC_ZIOWRITES_V, PhaFormatUInt64(ProcessItem->IoCounters.WriteOperationCount, TRUE)->Buffer); // writes SetDlgItemText(hwndDlg, IDC_ZIOWRITEBYTES_V, PhaFormatSize(ProcessItem->IoCounters.WriteTransferCount, -1)->Buffer); // write bytes SetDlgItemText(hwndDlg, IDC_ZIOOTHER_V, PhaFormatUInt64(ProcessItem->IoCounters.OtherOperationCount, TRUE)->Buffer); // other SetDlgItemText(hwndDlg, IDC_ZIOOTHERBYTES_V, PhaFormatSize(ProcessItem->IoCounters.OtherTransferCount, -1)->Buffer); // read bytes SetDlgItemText(hwndDlg, IDC_ZHANDLES_V, PhaFormatUInt64(ProcessItem->NumberOfHandles, TRUE)->Buffer); // handles // Optional information if (!PH_IS_FAKE_PROCESS_ID(ProcessItem->ProcessId)) { PPH_STRING peakHandles = NULL; PPH_STRING gdiHandles = NULL; PPH_STRING userHandles = NULL; PPH_STRING cycles = NULL; ULONG pagePriority = -1; IO_PRIORITY_HINT ioPriority = -1; PPH_STRING privateWs = NULL; PPH_STRING shareableWs = NULL; PPH_STRING sharedWs = NULL; BOOLEAN gotCycles = FALSE; BOOLEAN gotWsCounters = FALSE; if (ProcessItem->QueryHandle) { ULONG64 cycleTime; if (WindowsVersion >= WINDOWS_7) { PROCESS_HANDLE_INFORMATION handleInfo; if (NT_SUCCESS(NtQueryInformationProcess( ProcessItem->QueryHandle, ProcessHandleCount, &handleInfo, sizeof(PROCESS_HANDLE_INFORMATION), NULL ))) { peakHandles = PhaFormatUInt64(handleInfo.HandleCountHighWatermark, TRUE); } } gdiHandles = PhaFormatUInt64(GetGuiResources(ProcessItem->QueryHandle, GR_GDIOBJECTS), TRUE); // GDI handles userHandles = PhaFormatUInt64(GetGuiResources(ProcessItem->QueryHandle, GR_USEROBJECTS), TRUE); // USER handles if (WINDOWS_HAS_CYCLE_TIME && NT_SUCCESS(PhGetProcessCycleTime(ProcessItem->QueryHandle, &cycleTime))) { cycles = PhaFormatUInt64(cycleTime, TRUE); gotCycles = TRUE; } if (WindowsVersion >= WINDOWS_VISTA) { PhGetProcessPagePriority(ProcessItem->QueryHandle, &pagePriority); PhGetProcessIoPriority(ProcessItem->QueryHandle, &ioPriority); } } if (Context->ProcessHandle) { PH_PROCESS_WS_COUNTERS wsCounters; if (NT_SUCCESS(PhGetProcessWsCounters(Context->ProcessHandle, &wsCounters))) { privateWs = PhaFormatSize((ULONG64)wsCounters.NumberOfPrivatePages * PAGE_SIZE, -1); shareableWs = PhaFormatSize((ULONG64)wsCounters.NumberOfShareablePages * PAGE_SIZE, -1); sharedWs = PhaFormatSize((ULONG64)wsCounters.NumberOfSharedPages * PAGE_SIZE, -1); gotWsCounters = TRUE; } } if (WindowsVersion >= WINDOWS_7) { if (!gotCycles) cycles = PhaFormatUInt64(ProcessItem->CycleTimeDelta.Value, TRUE); if (!gotWsCounters) privateWs = PhaFormatSize(ProcessItem->WorkingSetPrivateSize, -1); } if (WindowsVersion >= WINDOWS_7) SetDlgItemText(hwndDlg, IDC_ZPEAKHANDLES_V, PhGetStringOrDefault(peakHandles, L"Unknown")); else SetDlgItemText(hwndDlg, IDC_ZPEAKHANDLES_V, L"N/A"); SetDlgItemText(hwndDlg, IDC_ZGDIHANDLES_V, PhGetStringOrDefault(gdiHandles, L"Unknown")); SetDlgItemText(hwndDlg, IDC_ZUSERHANDLES_V, PhGetStringOrDefault(userHandles, L"Unknown")); SetDlgItemText(hwndDlg, IDC_ZCYCLES_V, PhGetStringOrDefault(cycles, WINDOWS_HAS_CYCLE_TIME ? L"Unknown" : L"N/A")); if (WindowsVersion >= WINDOWS_VISTA) { if (pagePriority != -1 && pagePriority <= MEMORY_PRIORITY_NORMAL) SetDlgItemText(hwndDlg, IDC_ZPAGEPRIORITY_V, PhPagePriorityNames[pagePriority]); else SetDlgItemText(hwndDlg, IDC_ZPAGEPRIORITY_V, L"Unknown"); if (ioPriority != -1 && ioPriority < MaxIoPriorityTypes) SetDlgItemText(hwndDlg, IDC_ZIOPRIORITY_V, PhIoPriorityHintNames[ioPriority]); else SetDlgItemText(hwndDlg, IDC_ZIOPRIORITY_V, L"Unknown"); } else { SetDlgItemText(hwndDlg, IDC_ZPAGEPRIORITY_V, L"N/A"); SetDlgItemText(hwndDlg, IDC_ZIOPRIORITY_V, L"N/A"); } SetDlgItemText(hwndDlg, IDC_ZPRIVATEWS_V, PhGetStringOrDefault(privateWs, L"Unknown")); SetDlgItemText(hwndDlg, IDC_ZSHAREABLEWS_V, PhGetStringOrDefault(shareableWs, L"Unknown")); SetDlgItemText(hwndDlg, IDC_ZSHAREDWS_V, PhGetStringOrDefault(sharedWs, L"Unknown")); } else { SetDlgItemText(hwndDlg, IDC_ZPEAKHANDLES_V, L"N/A"); SetDlgItemText(hwndDlg, IDC_ZGDIHANDLES_V, L"N/A"); SetDlgItemText(hwndDlg, IDC_ZUSERHANDLES_V, L"N/A"); SetDlgItemText(hwndDlg, IDC_ZCYCLES_V, L"N/A"); SetDlgItemText(hwndDlg, IDC_ZPAGEPRIORITY_V, L"N/A"); SetDlgItemText(hwndDlg, IDC_ZIOPRIORITY_V, L"N/A"); SetDlgItemText(hwndDlg, IDC_ZPRIVATEWS_V, L"N/A"); SetDlgItemText(hwndDlg, IDC_ZSHAREABLEWS_V, L"N/A"); SetDlgItemText(hwndDlg, IDC_ZSHAREDWS_V, L"N/A"); } }
ULONG PerfUpdateInformation( VOID ) { ULONG i; ULONG64 TotalTime; PLIST_ENTRY ListEntry; LIST_ENTRY ListHead; PBSP_PROCESS Process; PPERF_INFORMATION Information; NTSTATUS Status; LIST_ENTRY FreeListHead; RtlZeroMemory(&PerfCpuTotal, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); Status = (*NtQuerySystemInformation)(SystemProcessorPerformanceInformation, PerfCpuInformation, PerfCpuInformationLength, NULL); ASSERT(Status == STATUS_SUCCESS); for (i = 0; i < BspProcessorNumber; i++) { PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION Cpu = &PerfCpuInformation[i]; Cpu->KernelTime.QuadPart -= Cpu->IdleTime.QuadPart + Cpu->DpcTime.QuadPart + Cpu->InterruptTime.QuadPart; PerfCpuTotal.DpcTime.QuadPart += Cpu->DpcTime.QuadPart; PerfCpuTotal.IdleTime.QuadPart += Cpu->IdleTime.QuadPart; PerfCpuTotal.InterruptCount += Cpu->InterruptCount; PerfCpuTotal.InterruptTime.QuadPart += Cpu->InterruptTime.QuadPart; PerfCpuTotal.KernelTime.QuadPart += Cpu->KernelTime.QuadPart; PerfCpuTotal.UserTime.QuadPart += Cpu->UserTime.QuadPart; PerfUpdateDelta(&PerfCpusKernelDelta[i], Cpu->KernelTime.QuadPart); PerfUpdateDelta(&PerfCpusUserDelta[i], Cpu->UserTime.QuadPart); PerfUpdateDelta(&PerfCpusOtherDelta[i], Cpu->IdleTime.QuadPart + Cpu->DpcTime.QuadPart + Cpu->InterruptTime.QuadPart); TotalTime = PerfCpusKernelDelta[i].Delta + PerfCpusUserDelta[i].Delta + PerfCpusOtherDelta[i].Delta; if (TotalTime != 0) { PerfCpusKernelUsage[i] = (FLOAT)PerfCpusKernelDelta[i].Delta / TotalTime; PerfCpusUserUsage[i] = (FLOAT)PerfCpusUserDelta[i].Delta / TotalTime; } else { PerfCpusKernelUsage[i] = 0; PerfCpusUserUsage[i] = 0; } } PerfUpdateDelta(&PerfCpuKernelDelta, PerfCpuTotal.KernelTime.QuadPart); PerfUpdateDelta(&PerfCpuUserDelta, PerfCpuTotal.UserTime.QuadPart); PerfUpdateDelta(&PerfCpuOtherDelta, PerfCpuTotal.IdleTime.QuadPart + PerfCpuTotal.DpcTime.QuadPart + PerfCpuTotal.InterruptTime.QuadPart); TotalTime = PerfCpuKernelDelta.Delta + PerfCpuUserDelta.Delta + PerfCpuOtherDelta.Delta; if (TotalTime) { PerfCpuKernelUsage = (FLOAT)PerfCpuKernelDelta.Delta / TotalTime; PerfCpuUserUsage = (FLOAT)PerfCpuUserDelta.Delta / TotalTime; } else { PerfCpuKernelUsage = 0; PerfCpuUserUsage = 0; } PerfTotalTime = TotalTime; InitializeListHead(&ListHead); InitializeListHead(&FreeListHead); BspQueryProcessList(&ListHead); ListEntry = PerfListHead.Flink; while (ListEntry != &PerfListHead) { HANDLE ProcessHandle; PROCESS_MEMORY_COUNTERS_EX MemoryCounters; IO_COUNTERS IoCounters; Information = CONTAINING_RECORD(ListEntry, PERF_INFORMATION, ListEntry); Process = BspQueryProcessById(&ListHead, Information->ProcessId); if (!Process) { ASSERT(Information->ProcessId != 0); ListEntry = ListEntry->Flink; Information->Terminated = TRUE; RemoveEntryList(&Information->ListEntry); InsertTailList(&FreeListHead, &Information->ListEntry); if (!PerfFirstRun) { PerfPushUpdateToConsumers(Information); } continue; } PerfUpdateDelta(&Information->CpuKernelDelta, Process->KernelTime.QuadPart); PerfUpdateDelta(&Information->CpuUserDelta, Process->UserTime.QuadPart); if (PerfTotalTime != 0) { Information->CpuKernelUsage = (FLOAT)Information->CpuKernelDelta.Delta / PerfTotalTime; Information->CpuUserUsage = (FLOAT)Information->CpuUserDelta.Delta / PerfTotalTime; Information->CpuTotalUsage = (FLOAT)Information->CpuKernelUsage + Information->CpuUserUsage; } else { Information->CpuKernelUsage = 0; Information->CpuUserUsage = 0; Information->CpuTotalUsage = 0; } ProcessHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, Process->ProcessId); GetProcessMemoryInfo(ProcessHandle, (PPROCESS_MEMORY_COUNTERS)&MemoryCounters, sizeof(MemoryCounters)); GetProcessIoCounters(ProcessHandle, &IoCounters); PerfUpdateDelta(&Information->PrivateDelta, MemoryCounters.PrivateUsage); PerfUpdateDelta(&Information->WorkingSetDelta, MemoryCounters.WorkingSetSize); Information->WorkingSetPeak = MemoryCounters.PeakWorkingSetSize; PerfUpdateDelta(&Information->VirtualDelta, Process->VirtualBytes); PerfUpdateDelta(&Information->IoReadDelta, IoCounters.ReadTransferCount); PerfUpdateDelta(&Information->IoWriteDelta, IoCounters.WriteTransferCount); Information->KernelHandles = Process->KernelHandleCount; Information->UserHandles = GetGuiResources(ProcessHandle, GR_USEROBJECTS); Information->GdiHandles = GetGuiResources(ProcessHandle, GR_GDIOBJECTS); CloseHandle(ProcessHandle); if (Information->KernelHandlesPeak < Information->KernelHandles) { Information->KernelHandlesPeak = Information->KernelHandles; } if (Information->UserHandlesPeak < Information->UserHandles) { Information->UserHandlesPeak = Information->UserHandles; } if (Information->GdiHandlesPeak < Information->GdiHandles) { Information->GdiHandlesPeak = Information->GdiHandles; } // // Notify all performance data consumers via registered callback objects // if (!PerfFirstRun) { PerfPushUpdateToConsumers(Information); } ListEntry = ListEntry->Flink; } // // Deallocate died PERF_INFORMATION structures // while (IsListEmpty(&FreeListHead) != TRUE) { ListEntry = RemoveHeadList(&FreeListHead); Information = CONTAINING_RECORD(ListEntry, PERF_INFORMATION, ListEntry); BspFree(Information); } BspFreeProcessList(&ListHead); if (PerfFirstRun) { PerfFirstRun = FALSE; } return 0; }
/* The following block is copied from the Java source code. It documents the counters array. * @param counters the results are returned in this array. * <ol> * <li>working set in bytes for this process * <li>peak working set in bytes for this process * <li>elapsed time in milliseconds * <li>user time in milliseconds * <li>kernel time in milliseconds * <li>page faults for the process * <li>commit charge total in bytes (working set for the entire machine). On some * machines we have problems getting this value so we return -1 in that case. * <li>number of GDI objects in the process * <li>number of USER objects in the process * <li>number of open handles in the process. returns -1 if this information is not available * <li>Number of read operations * <li>Number of write operations * <li>Number of bytes read * <li>Number of bytes written * </ol> */ JNIEXPORT jboolean JNICALL Java_org_eclipse_perfmsr_core_PerformanceMonitor_nativeGetPerformanceCounters (JNIEnv * jniEnv, jclass jniClass, jlongArray counters) { FILETIME creationTime, exitTime, kernelTime, userTime, systemTime; ULARGE_INTEGER uliCreation, uliSystem, uliKernel, uliUser; ULONGLONG diff; IO_COUNTERS ioCounters; jboolean result = TRUE; jsize len = (*jniEnv)->GetArrayLength(jniEnv, counters); jlong *body = (*jniEnv)->GetLongArrayElements(jniEnv, counters, 0); HANDLE me = GetCurrentProcess(); PROCESS_MEMORY_COUNTERS memCounters; DWORD cb = sizeof(PROCESS_MEMORY_COUNTERS); BOOL rc = GetProcessMemoryInfo(me, &memCounters, cb); if (rc != 0) { body[0] = memCounters.WorkingSetSize; body[1] = memCounters.PeakWorkingSetSize; body[5] = memCounters.PageFaultCount; } else { handleSystemError(jniEnv); return FALSE; } if (!GetProcessTimes(me, &creationTime, &exitTime, &kernelTime, &userTime)) { handleSystemError(jniEnv); return FALSE; } GetSystemTimeAsFileTime(&systemTime); memcpy(&uliCreation, &creationTime, sizeof(uliCreation)); memcpy(&uliSystem, &systemTime, sizeof(uliSystem)); memcpy(&uliKernel, &kernelTime, sizeof(uliSystem)); memcpy(&uliUser, &userTime, sizeof(ULARGE_INTEGER)); diff = uliSystem.QuadPart - uliCreation.QuadPart; body[2] = diff / 10000; body[3] = uliUser.QuadPart / 10000; body[4] = uliKernel.QuadPart / 10000; body[6] = getTotalCommitted(jniEnv); body[7] = GetGuiResources(me, GR_GDIOBJECTS); body[8] = GetGuiResources(me, GR_USEROBJECTS); body[9] = getHandleCount(jniEnv, me); if (!GetProcessIoCounters(me, &ioCounters)) { handleSystemError(jniEnv); return FALSE; } body[10] = ioCounters.ReadOperationCount; body[11] = ioCounters.WriteOperationCount; body[12] = ioCounters.ReadTransferCount; body[13] = ioCounters.WriteTransferCount; (*jniEnv)->ReleaseLongArrayElements(jniEnv, counters, body, 0); return result; }
PLUGIN_EXPORT double Update(void* data) { MeasureData* measure = (MeasureData*)data; // count the existing window objects if (measure->type == WINDOW_COUNT) { g_WindowCount = 0; EnumChildWindows(NULL, EnumWindowProc, 0); return g_WindowCount; } const WCHAR* processName = measure->process.c_str(); bool name = !measure->process.empty(); DWORD aProcesses[1024]; DWORD bytesNeeded; WCHAR buffer[1024]; HMODULE hMod[1024]; DWORD cbNeeded; if (!EnumProcesses(aProcesses, sizeof(aProcesses), &bytesNeeded)) { return 0.0; } // step through the running processes DWORD flags = PROCESS_QUERY_INFORMATION; if (name) { flags |= PROCESS_VM_READ; } UINT resourceCount = 0; for (UINT i = 0, isize = bytesNeeded / sizeof(DWORD); i < isize; ++i) { HANDLE hProcess = OpenProcess(flags, true, aProcesses[i]); if (hProcess != NULL) { if (name) { if (EnumProcessModules(hProcess, hMod, sizeof(hMod), &cbNeeded)) { if (GetModuleBaseName(hProcess, hMod[0], buffer, sizeof(buffer))) { if (_wcsicmp(buffer, processName) != 0) { CloseHandle(hProcess); continue; } } else { CloseHandle(hProcess); continue; } } else { CloseHandle(hProcess); continue; } } if (measure->type == GDI_COUNT) { resourceCount += GetGuiResources(hProcess, GR_GDIOBJECTS); } else if (measure->type == USER_COUNT) { resourceCount += GetGuiResources(hProcess, GR_USEROBJECTS); } else if (measure->type == HANDLE_COUNT) { DWORD tempHandleCount = 0; GetProcessHandleCount(hProcess, &tempHandleCount); resourceCount += tempHandleCount; } } CloseHandle(hProcess); } return resourceCount; }
void PerfDataRefresh(void) { ULONG ulSize; NTSTATUS status; LPBYTE pBuffer; ULONG BufferSize; PSYSTEM_PROCESS_INFORMATION pSPI; PPERFDATA pPDOld; ULONG Idx, Idx2; HANDLE hProcess; HANDLE hProcessToken; SYSTEM_PERFORMANCE_INFORMATION SysPerfInfo; SYSTEM_TIMEOFDAY_INFORMATION SysTimeInfo; SYSTEM_FILECACHE_INFORMATION SysCacheInfo; LPBYTE SysHandleInfoData; PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION SysProcessorTimeInfo; double CurrentKernelTime; PSECURITY_DESCRIPTOR ProcessSD; PSID ProcessUser; ULONG Buffer[64]; /* must be 4 bytes aligned! */ ULONG cwcUserName; /* Get new system time */ status = NtQuerySystemInformation(SystemTimeOfDayInformation, &SysTimeInfo, sizeof(SysTimeInfo), NULL); if (!NT_SUCCESS(status)) return; /* Get new CPU's idle time */ status = NtQuerySystemInformation(SystemPerformanceInformation, &SysPerfInfo, sizeof(SysPerfInfo), NULL); if (!NT_SUCCESS(status)) return; /* Get system cache information */ status = NtQuerySystemInformation(SystemFileCacheInformation, &SysCacheInfo, sizeof(SysCacheInfo), NULL); if (!NT_SUCCESS(status)) return; /* Get processor time information */ SysProcessorTimeInfo = (PSYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)HeapAlloc(GetProcessHeap(), 0, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * SystemBasicInfo.NumberOfProcessors); status = NtQuerySystemInformation(SystemProcessorPerformanceInformation, SysProcessorTimeInfo, sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION) * SystemBasicInfo.NumberOfProcessors, &ulSize); if (!NT_SUCCESS(status)) { if (SysProcessorTimeInfo != NULL) HeapFree(GetProcessHeap(), 0, SysProcessorTimeInfo); return; } /* Get handle information * We don't know how much data there is so just keep * increasing the buffer size until the call succeeds */ BufferSize = 0; do { BufferSize += 0x10000; SysHandleInfoData = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, BufferSize); status = NtQuerySystemInformation(SystemHandleInformation, SysHandleInfoData, BufferSize, &ulSize); if (status == STATUS_INFO_LENGTH_MISMATCH) { HeapFree(GetProcessHeap(), 0, SysHandleInfoData); } } while (status == STATUS_INFO_LENGTH_MISMATCH); /* Get process information * We don't know how much data there is so just keep * increasing the buffer size until the call succeeds */ BufferSize = 0; do { BufferSize += 0x10000; pBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, BufferSize); status = NtQuerySystemInformation(SystemProcessInformation, pBuffer, BufferSize, &ulSize); if (status == STATUS_INFO_LENGTH_MISMATCH) { HeapFree(GetProcessHeap(), 0, pBuffer); } } while (status == STATUS_INFO_LENGTH_MISMATCH); EnterCriticalSection(&PerfDataCriticalSection); /* * Save system performance info */ memcpy(&SystemPerfInfo, &SysPerfInfo, sizeof(SYSTEM_PERFORMANCE_INFORMATION)); /* * Save system cache info */ memcpy(&SystemCacheInfo, &SysCacheInfo, sizeof(SYSTEM_FILECACHE_INFORMATION)); /* * Save system processor time info */ if (SystemProcessorTimeInfo) { HeapFree(GetProcessHeap(), 0, SystemProcessorTimeInfo); } SystemProcessorTimeInfo = SysProcessorTimeInfo; /* * Save system handle info */ memcpy(&SystemHandleInfo, SysHandleInfoData, sizeof(SYSTEM_HANDLE_INFORMATION)); HeapFree(GetProcessHeap(), 0, SysHandleInfoData); for (CurrentKernelTime=0, Idx=0; Idx<(ULONG)SystemBasicInfo.NumberOfProcessors; Idx++) { CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].KernelTime); CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].DpcTime); CurrentKernelTime += Li2Double(SystemProcessorTimeInfo[Idx].InterruptTime); } /* If it's a first call - skip idle time calcs */ if (liOldIdleTime.QuadPart != 0) { /* CurrentValue = NewValue - OldValue */ dbIdleTime = Li2Double(SysPerfInfo.IdleProcessTime) - Li2Double(liOldIdleTime); dbKernelTime = CurrentKernelTime - OldKernelTime; dbSystemTime = Li2Double(SysTimeInfo.CurrentTime) - Li2Double(liOldSystemTime); /* CurrentCpuIdle = IdleTime / SystemTime */ dbIdleTime = dbIdleTime / dbSystemTime; dbKernelTime = dbKernelTime / dbSystemTime; /* CurrentCpuUsage% = 100 - (CurrentCpuIdle * 100) / NumberOfProcessors */ dbIdleTime = 100.0 - dbIdleTime * 100.0 / (double)SystemBasicInfo.NumberOfProcessors; /* + 0.5; */ dbKernelTime = 100.0 - dbKernelTime * 100.0 / (double)SystemBasicInfo.NumberOfProcessors; /* + 0.5; */ } /* Store new CPU's idle and system time */ liOldIdleTime = SysPerfInfo.IdleProcessTime; liOldSystemTime = SysTimeInfo.CurrentTime; OldKernelTime = CurrentKernelTime; /* Determine the process count * We loop through the data we got from NtQuerySystemInformation * and count how many structures there are (until RelativeOffset is 0) */ ProcessCountOld = ProcessCount; ProcessCount = 0; pSPI = (PSYSTEM_PROCESS_INFORMATION)pBuffer; while (pSPI) { ProcessCount++; if (pSPI->NextEntryOffset == 0) break; pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->NextEntryOffset); } /* Now alloc a new PERFDATA array and fill in the data */ pPerfData = (PPERFDATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PERFDATA) * ProcessCount); pSPI = (PSYSTEM_PROCESS_INFORMATION)pBuffer; for (Idx=0; Idx<ProcessCount; Idx++) { /* Get the old perf data for this process (if any) */ /* so that we can establish delta values */ pPDOld = NULL; if (pPerfDataOld) { for (Idx2=0; Idx2<ProcessCountOld; Idx2++) { if (pPerfDataOld[Idx2].ProcessId == pSPI->UniqueProcessId) { pPDOld = &pPerfDataOld[Idx2]; break; } } } if (pSPI->ImageName.Buffer) { /* Don't assume a UNICODE_STRING Buffer is zero terminated: */ int len = pSPI->ImageName.Length / 2; /* Check against max size and allow for terminating zero (already zeroed): */ if(len >= MAX_PATH)len=MAX_PATH - 1; wcsncpy(pPerfData[Idx].ImageName, pSPI->ImageName.Buffer, len); } else { LoadStringW(hInst, IDS_IDLE_PROCESS, pPerfData[Idx].ImageName, sizeof(pPerfData[Idx].ImageName) / sizeof(pPerfData[Idx].ImageName[0])); } pPerfData[Idx].ProcessId = pSPI->UniqueProcessId; if (pPDOld) { double CurTime = Li2Double(pSPI->KernelTime) + Li2Double(pSPI->UserTime); double OldTime = Li2Double(pPDOld->KernelTime) + Li2Double(pPDOld->UserTime); double CpuTime = (CurTime - OldTime) / dbSystemTime; CpuTime = CpuTime * 100.0 / (double)SystemBasicInfo.NumberOfProcessors; /* + 0.5; */ pPerfData[Idx].CPUUsage = (ULONG)CpuTime; } pPerfData[Idx].CPUTime.QuadPart = pSPI->UserTime.QuadPart + pSPI->KernelTime.QuadPart; pPerfData[Idx].WorkingSetSizeBytes = pSPI->WorkingSetSize; pPerfData[Idx].PeakWorkingSetSizeBytes = pSPI->PeakWorkingSetSize; if (pPDOld) pPerfData[Idx].WorkingSetSizeDelta = labs((LONG)pSPI->WorkingSetSize - (LONG)pPDOld->WorkingSetSizeBytes); else pPerfData[Idx].WorkingSetSizeDelta = 0; pPerfData[Idx].PageFaultCount = pSPI->PageFaultCount; if (pPDOld) pPerfData[Idx].PageFaultCountDelta = labs((LONG)pSPI->PageFaultCount - (LONG)pPDOld->PageFaultCount); else pPerfData[Idx].PageFaultCountDelta = 0; pPerfData[Idx].VirtualMemorySizeBytes = pSPI->VirtualSize; pPerfData[Idx].PagedPoolUsagePages = pSPI->QuotaPeakPagedPoolUsage; pPerfData[Idx].NonPagedPoolUsagePages = pSPI->QuotaPeakNonPagedPoolUsage; pPerfData[Idx].BasePriority = pSPI->BasePriority; pPerfData[Idx].HandleCount = pSPI->HandleCount; pPerfData[Idx].ThreadCount = pSPI->NumberOfThreads; pPerfData[Idx].SessionId = pSPI->SessionId; pPerfData[Idx].UserName[0] = UNICODE_NULL; pPerfData[Idx].USERObjectCount = 0; pPerfData[Idx].GDIObjectCount = 0; ProcessUser = SystemUserSid; ProcessSD = NULL; if (pSPI->UniqueProcessId != NULL) { hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | READ_CONTROL, FALSE, PtrToUlong(pSPI->UniqueProcessId)); if (hProcess) { /* don't query the information of the system process. It's possible but returns Administrators as the owner of the process instead of SYSTEM */ if (pSPI->UniqueProcessId != (HANDLE)0x4) { if (OpenProcessToken(hProcess, TOKEN_QUERY, &hProcessToken)) { DWORD RetLen = 0; BOOL Ret; Ret = GetTokenInformation(hProcessToken, TokenUser, (LPVOID)Buffer, sizeof(Buffer), &RetLen); CloseHandle(hProcessToken); if (Ret) ProcessUser = ((PTOKEN_USER)Buffer)->User.Sid; else goto ReadProcOwner; } else { ReadProcOwner: GetSecurityInfo(hProcess, SE_KERNEL_OBJECT, OWNER_SECURITY_INFORMATION, &ProcessUser, NULL, NULL, NULL, &ProcessSD); } pPerfData[Idx].USERObjectCount = GetGuiResources(hProcess, GR_USEROBJECTS); pPerfData[Idx].GDIObjectCount = GetGuiResources(hProcess, GR_GDIOBJECTS); } GetProcessIoCounters(hProcess, &pPerfData[Idx].IOCounters); CloseHandle(hProcess); } else { goto ClearInfo; } } else { ClearInfo: /* clear information we were unable to fetch */ ZeroMemory(&pPerfData[Idx].IOCounters, sizeof(IO_COUNTERS)); } cwcUserName = sizeof(pPerfData[0].UserName) / sizeof(pPerfData[0].UserName[0]); CachedGetUserFromSid(ProcessUser, pPerfData[Idx].UserName, &cwcUserName); if (ProcessSD != NULL) { LocalFree((HLOCAL)ProcessSD); } pPerfData[Idx].UserTime.QuadPart = pSPI->UserTime.QuadPart; pPerfData[Idx].KernelTime.QuadPart = pSPI->KernelTime.QuadPart; pSPI = (PSYSTEM_PROCESS_INFORMATION)((LPBYTE)pSPI + pSPI->NextEntryOffset); } HeapFree(GetProcessHeap(), 0, pBuffer); if (pPerfDataOld) { HeapFree(GetProcessHeap(), 0, pPerfDataOld); } pPerfDataOld = pPerfData; LeaveCriticalSection(&PerfDataCriticalSection); }