Reputation: 2888
Looking for Win32 API functions, C++ or Delphi sample code that tells me the CPU usage (percent and/or total CPU time) of a thread (not the total for a process). I have the thread ID.
I know that Sysinternals Process Explorer can display this information, but I need this information inside my program.
Upvotes: 24
Views: 37823
Reputation: 2422
This example uses GetProcessTimes()
but can easily be modified to use GetThreadTimes()
.
ISO C's clock()
is SUPPOSED to give you elapsed CPU-seconds when divided by CLOCKS_PER_SEC
. However the Visual Studio 2019 web page says:
The clock function tells how much wall-clock time has passed since the CRT initialization during process start. Note that this function does not strictly conform to ISO C, which specifies net CPU time as the return value.
So, here is a stand-in I made. On Windows 7/Visual Studio 2017, CLOCKS_PER_SEC
is 1000 and GetProcessTimes()
only has millisecond accuracy, so no accuracy is lost returning clock_t
instead of double
, say.
clock_t AKClock() {
#ifdef WIN32
FILETIME ftimeCreate, ftimeExit, ftimeKernel, ftimeUser;
SYSTEMTIME stimeKernel, stimeUser;
if ( ! GetProcessTimes( GetCurrentProcess(), &ftimeCreate, &ftimeExit,
&ftimeKernel, &ftimeUser ) ||
! FileTimeToSystemTime( &ftimeKernel, &stimeKernel ) ||
! FileTimeToSystemTime( &ftimeUser, &stimeUser ) ) {
char szError[ 1024 ];
MyLoggingFunction( "AKClock() failed; returning -1: %s",
AKGetLastError( szError, sizeof( szError ) ) );
return (clock_t) -1.0;
}
return (clock_t)
( ( stimeKernel.wHour * 3600.0 +
stimeKernel.wMinute * 60.0 +
stimeKernel.wSecond +
stimeKernel.wMilliseconds / 1000.0 +
stimeUser.wHour * 3600.0 +
stimeUser.wMinute * 60.0 +
stimeUser.wSecond +
stimeUser.wMilliseconds / 1000.0 ) * CLOCKS_PER_SEC );
#else
return clock();
#endif
}
And for completeness, here's AKGetLastError():
void AKstrncpy( char *pszDest, const char *pszSrc, const size_t sDest ) {
strncpy( pszDest, pszSrc, sDest );
pszDest[ sDest - 1 ] = '\0';
}
char* AKGetLastError( char* szBuf, int iBufSize ) {
DWORD errorMessageID = GetLastError();
char* pszError = NULL;
size_t sizeBuf;
if( errorMessageID == 0 ) {
AKstrncpy( szBuf, "(no error)", iBufSize );
return szBuf;
}
sizeBuf = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
(LPSTR) &pszError, 0, NULL );
AKstrncpy( szBuf, pszError, iBufSize );
LocalFree( pszError );
int iLen = strlen( szBuf );
if ( strcmp( szBuf + iLen - 2, "\r\n" ) == 0 )
szBuf[ iLen - 2 ] = '\0';
return szBuf;
}
Upvotes: 1
Reputation: 11871
Here is a simple WMI query wrapper. With help of it you can call this to get data:
getWmiQueryResult(L"SELECT PercentProcessorTime FROM Win32_PerfRawData_PerfProc_Thread WHERE IdProcess=4 and IdThread=8", L"PercentProcessorTime ");
Also you might want to look at the Win32_PerfRawData_PerfProc_Thread documentation to see what other properties you can fetch.
Upvotes: 1
Reputation: 8174
Is important to know that in certain situations, the execution time of a thread may be worthless.
The execution times of each thread are updated every 15 milliseconds usually for multi-core systems, so if a thread completes its task before this time, the runtime will be reset.
More details can be obtained on the link:
GetThreadTimes function and I was surprised by the result!
and
Why GetThreadTimes is wrong
Upvotes: 8
Reputation: 2888
With the help of RRUZ's answer above I finally came up with this code for Borland Delphi:
const
THREAD_TERMINATE = $0001;
THREAD_SUSPEND_RESUME = $0002;
THREAD_GET_CONTEXT = $0008;
THREAD_SET_CONTEXT = $0010;
THREAD_SET_INFORMATION = $0020;
THREAD_QUERY_INFORMATION = $0040;
THREAD_SET_THREAD_TOKEN = $0080;
THREAD_IMPERSONATE = $0100;
THREAD_DIRECT_IMPERSONATION = $0200;
THREAD_SET_LIMITED_INFORMATION = $0400;
THREAD_QUERY_LIMITED_INFORMATION = $0800;
THREAD_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED or SYNCHRONIZE or $03FF;
function OpenThread(dwDesiredAccess: DWord;
bInheritHandle: Bool;
dwThreadId: DWord): DWord; stdcall; external 'kernel32.dll';
procedure TForm1.Button1Click(Sender: TObject);
var iii:integer;
handle:thandle;
creationtime,exittime,kerneltime,usertime:filetime;
begin
Handle:=OpenThread(THREAD_SET_INFORMATION or THREAD_QUERY_INFORMATION, False, windows.GetCurrentThreadId);
if handle<>0 then
begin
getthreadtimes(Handle,creationtime,exittime,kerneltime,usertime);
label1.caption:='Total time for Thread #'+inttostr(windows.GetCurrentThreadId)+': '+inttostr( (int64(kerneltime)+int64(usertime)) div 1000 )+' msec';
CloseHandle(Handle);
end;
end;
Upvotes: 6
Reputation: 15538
The data you are refering to is available using specific WMI calls. You can query Win32_Process to get all sorts of process specific information, and query Win32_PerfFormattedData_PerfProc_Process to get the thread count, and given a handle to a thread (what I believe your looking for) you can query Win32_PerfRawData_PerfProc_Thread to get the percent of processor time used.
There is a library available for Delphi which provides wrappers for most of the WMI queries, however it will take some experimentation to get the exact query your looking for. The query syntax is very sql like, for example on my system to return the percent of processor time for threadid 8, for process id 4 is:
SELECT PercentProcessorTime FROM Win32_PerfRawData_PerfProc_Thread
WHERE IdProcess=4 and IdThread=8
Most of the programs which present statistical information about running processes now use WMI to query for this information.
Upvotes: 11
Reputation: 136391
You must use these functions to get the cpu usage per thread and process.
GetThreadTimes (Retrieves timing information for the specified thread.)
GetProcessTimes (Retrieves timing information for the specified process.)
GetSystemTime (Retrieves the current system date and time. The system time is expressed in Coordinated Universal Time UTC)
Here a excellent article from Dr. Dobb's Win32 Performance Measurement Options
Bye.
Upvotes: 29
Reputation: 62323
Using "GetThreadTimes"? If you measure the time between calls to "GetThreadTimes" and store the previous user and/or kernel times then you know how much time the thread has had since you last checked. You also know how much time has elapsed in the mean time and thus you can work out how much CPU time was used. It would be best (for timer resolution reasons) to make this check every second or so and work out its average CPU usage over that second.
Upvotes: 4