私はかつて、実行中のアプリケーションの内部から次のパフォーマンスパラメータを決定するという課題を抱えていました。
コードはWindowsとLinuxで実行する必要がありました。これは標準的な作業と思われますが、マニュアル(WIN32 API、GNU docs)、およびインターネットで必要な情報を見つけるのに数日かかりました。このトピックに関する情報はそこにあります。
他の人が同じトラブルを経験するのを防ぐために、散らばったすべての情報に加えて、試行錯誤で見つけたものを1か所に集めておくことをお勧めします。
上記の値のいくつかは適切なWIN32 APIから簡単に入手できます。完全を期すためにここにリストしています。しかし、他の人はPerformance Data Helperライブラリー(PDH)から入手する必要があります。これは少し "直観的ではない"ので、作業にはかなりの試行錯誤が必要です。 (少なくともそれは私にかなりの時間がかかった、おそらく私はほんの少しバカだった…)
注:わかりやすくするために、次のコードではすべてのエラーチェックが省略されています。戻りコードを確認してください。
合計仮想メモリ:
#include "windows.h"
MEMORYSTATUSEX memInfo;
memInfo.dwLength = sizeof(MEMORYSTATUSEX);
GlobalMemoryStatusEx(&memInfo);
DWORDLONG totalVirtualMem = memInfo.ullTotalPageFile;
注: "TotalPageFile"という名前は、ここでは少し誤解を招きます。実際には、このパラメータはスワップファイルとインストールされているRAMのサイズである「仮想メモリサイズ」を与えます。
現在使用されている仮想メモリ
「合計仮想メモリ」と同じコード
DWORDLONG virtualMemUsed = memInfo.ullTotalPageFile - memInfo.ullAvailPageFile;
現在のプロセスが現在使用している仮想メモリ
#include "windows.h"
#include "psapi.h"
PROCESS_MEMORY_COUNTERS_EX pmc;
GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
SIZE_T virtualMemUsedByMe = pmc.PrivateUsage;
総物理メモリ(RAM):
「合計仮想メモリ」と同じコード
DWORDLONG totalPhysMem = memInfo.ullTotalPhys;
現在使用されている物理メモリ
Same code as in "Total Virtual Memory" and then
DWORDLONG physMemUsed = memInfo.ullTotalPhys - memInfo.ullAvailPhys;
現在のプロセスが現在使用している物理メモリ
「現在のプロセスが現在使用している仮想メモリ」と同じコード
SIZE_T physMemUsedByMe = pmc.WorkingSetSize;
現在使用されているCPU
#include "TCHAR.h"
#include "pdh.h"
static PDH_HQUERY cpuQuery;
static PDH_HCOUNTER cpuTotal;
void init(){
PdhOpenQuery(NULL, NULL, &cpuQuery);
// You can also use L"\\Processor(*)\\% Processor Time" and get individual CPU values with PdhGetFormattedCounterArray()
PdhAddEnglishCounter(cpuQuery, L"\\Processor(_Total)\\% Processor Time", NULL, &cpuTotal);
PdhCollectQueryData(cpuQuery);
}
double getCurrentValue(){
PDH_FMT_COUNTERVALUE counterVal;
PdhCollectQueryData(cpuQuery);
PdhGetFormattedCounterValue(cpuTotal, PDH_FMT_DOUBLE, NULL, &counterVal);
return counterVal.doubleValue;
}
現在のプロセスが現在使用しているCPU
#include "windows.h"
static ULARGE_INTEGER lastCPU, lastSysCPU, lastUserCPU;
static int numProcessors;
static HANDLE self;
void init(){
SYSTEM_INFO sysInfo;
FILETIME ftime, fsys, fuser;
GetSystemInfo(&sysInfo);
numProcessors = sysInfo.dwNumberOfProcessors;
GetSystemTimeAsFileTime(&ftime);
memcpy(&lastCPU, &ftime, sizeof(FILETIME));
self = GetCurrentProcess();
GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser);
memcpy(&lastSysCPU, &fsys, sizeof(FILETIME));
memcpy(&lastUserCPU, &fuser, sizeof(FILETIME));
}
double getCurrentValue(){
FILETIME ftime, fsys, fuser;
ULARGE_INTEGER now, sys, user;
double percent;
GetSystemTimeAsFileTime(&ftime);
memcpy(&now, &ftime, sizeof(FILETIME));
GetProcessTimes(self, &ftime, &ftime, &fsys, &fuser);
memcpy(&sys, &fsys, sizeof(FILETIME));
memcpy(&user, &fuser, sizeof(FILETIME));
percent = (sys.QuadPart - lastSysCPU.QuadPart) +
(user.QuadPart - lastUserCPU.QuadPart);
percent /= (now.QuadPart - lastCPU.QuadPart);
percent /= numProcessors;
lastCPU = now;
lastUserCPU = user;
lastSysCPU = sys;
return percent * 100;
}
Linuxでは、最初は明らかになったと思われる選択はgetrusage()
などのPOSIX APIを使用することでした。これを機能させるためにしばらく時間をかけましたが、意味のある値は得られませんでした。私がようやくカーネルソース自体を調べたとき、私はこれらのAPIがLinuxカーネル2.6の時点でまだ完全には実装されていないように思えました!?
結局私は、擬似ファイルシステムの/proc
とカーネルの呼び出しを組み合わせて全ての値を取得しました。
合計仮想メモリ:
#include "sys/types.h"
#include "sys/sysinfo.h"
struct sysinfo memInfo;
sysinfo (&memInfo);
long long totalVirtualMem = memInfo.totalram;
//Add other values in next statement to avoid int overflow on right hand side...
totalVirtualMem += memInfo.totalswap;
totalVirtualMem *= memInfo.mem_unit;
現在使用されている仮想メモリ
「合計仮想メモリ」と同じコード
long long virtualMemUsed = memInfo.totalram - memInfo.freeram;
//Add other values in next statement to avoid int overflow on right hand side...
virtualMemUsed += memInfo.totalswap - memInfo.freeswap;
virtualMemUsed *= memInfo.mem_unit;
現在のプロセスが現在使用している仮想メモリ
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
int parseLine(char* line){
// This assumes that a digit will be found and the line ends in " Kb".
int i = strlen(line);
const char* p = line;
while (*p <'0' || *p > '9') p++;
line[i-3] = '\0';
i = atoi(p);
return i;
}
int getValue(){ //Note: this value is in KB!
FILE* file = fopen("/proc/self/status", "r");
int result = -1;
char line[128];
while (fgets(line, 128, file) != NULL){
if (strncmp(line, "VmSize:", 7) == 0){
result = parseLine(line);
break;
}
}
fclose(file);
return result;
}
総物理メモリ(RAM):
「合計仮想メモリ」と同じコード
long long totalPhysMem = memInfo.totalram;
//Multiply in next statement to avoid int overflow on right hand side...
totalPhysMem *= memInfo.mem_unit;
現在使用されている物理メモリ
「合計仮想メモリ」と同じコード
long long physMemUsed = memInfo.totalram - memInfo.freeram;
//Multiply in next statement to avoid int overflow on right hand side...
physMemUsed *= memInfo.mem_unit;
現在のプロセスが現在使用している物理メモリ
「現在のプロセスが現在使用している仮想メモリ」のgetValue()を次のように変更します。
int getValue(){ //Note: this value is in KB!
FILE* file = fopen("/proc/self/status", "r");
int result = -1;
char line[128];
while (fgets(line, 128, file) != NULL){
if (strncmp(line, "VmRSS:", 6) == 0){
result = parseLine(line);
break;
}
}
fclose(file);
return result;
}
現在使用されているCPU
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
static unsigned long long lastTotalUser, lastTotalUserLow, lastTotalSys, lastTotalIdle;
void init(){
FILE* file = fopen("/proc/stat", "r");
fscanf(file, "cpu %llu %llu %llu %llu", &lastTotalUser, &lastTotalUserLow,
&lastTotalSys, &lastTotalIdle);
fclose(file);
}
double getCurrentValue(){
double percent;
FILE* file;
unsigned long long totalUser, totalUserLow, totalSys, totalIdle, total;
file = fopen("/proc/stat", "r");
fscanf(file, "cpu %llu %llu %llu %llu", &totalUser, &totalUserLow,
&totalSys, &totalIdle);
fclose(file);
if (totalUser < lastTotalUser || totalUserLow < lastTotalUserLow ||
totalSys < lastTotalSys || totalIdle < lastTotalIdle){
//Overflow detection. Just skip this value.
percent = -1.0;
}
else{
total = (totalUser - lastTotalUser) + (totalUserLow - lastTotalUserLow) +
(totalSys - lastTotalSys);
percent = total;
total += (totalIdle - lastTotalIdle);
percent /= total;
percent *= 100;
}
lastTotalUser = totalUser;
lastTotalUserLow = totalUserLow;
lastTotalSys = totalSys;
lastTotalIdle = totalIdle;
return percent;
}
現在のプロセスが現在使用しているCPU
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
#include "sys/times.h"
#include "sys/vtimes.h"
static clock_t lastCPU, lastSysCPU, lastUserCPU;
static int numProcessors;
void init(){
FILE* file;
struct tms timeSample;
char line[128];
lastCPU = times(&timeSample);
lastSysCPU = timeSample.tms_stime;
lastUserCPU = timeSample.tms_utime;
file = fopen("/proc/cpuinfo", "r");
numProcessors = 0;
while(fgets(line, 128, file) != NULL){
if (strncmp(line, "processor", 9) == 0) numProcessors++;
}
fclose(file);
}
double getCurrentValue(){
struct tms timeSample;
clock_t now;
double percent;
now = times(&timeSample);
if (now <= lastCPU || timeSample.tms_stime < lastSysCPU ||
timeSample.tms_utime < lastUserCPU){
//Overflow detection. Just skip this value.
percent = -1.0;
}
else{
percent = (timeSample.tms_stime - lastSysCPU) +
(timeSample.tms_utime - lastUserCPU);
percent /= (now - lastCPU);
percent /= numProcessors;
percent *= 100;
}
lastCPU = now;
lastSysCPU = timeSample.tms_stime;
lastUserCPU = timeSample.tms_utime;
return percent;
}
私は、/ proc疑似ファイルシステムを読む部分を除いて、LinuxコードのいくつかはUnixでも動作すると思います。おそらくUnixでは、これらの部分はgetrusage()
やそれに似た関数で置き換えることができますか?もしUnixのノウハウを持っている人がこの答えを編集して詳細を記入することができたら!
私はMac OS Xについても同様の情報を見つけたいと思っていました。ここにはなかったので、私は出かけて自分で掘り下げました。これが私が見つけたもののいくつかです。他に何か提案があるならば、私はそれらを聞きたいです。
Mac OS XではLinuxのようにプリセットのスワップパーティションやファイルを使用しないため、これは注意が必要です。これがAppleのドキュメントからのエントリです:
注:ほとんどのUnixベースのオペレーティングシステムとは異なり、Mac OS Xは仮想メモリに事前割り当てされたスワップパーティションを使用しません。代わりに、コンピュータのブートパーティションの利用可能なスペースすべてを使用します。
ですから、まだ利用可能な仮想メモリの量を知りたい場合は、ルートパーティションのサイズを取得する必要があります。あなたはこのようにすることができます:
struct statfs stats;
if (0 == statfs("/", &stats))
{
myFreeSwap = (uint64_t)stats.f_bsize * stats.f_bfree;
}
"vm.swapusage"キーを使ってsystclを呼び出すと、スワップの使用に関する興味深い情報が得られます。
sysctl -n vm.swapusage
vm.swapusage: total = 3072.00M used = 2511.78M free = 560.22M (encrypted)
上記のセクションで説明したように、スワップがさらに必要になると、ここに表示される合計スワップ使用量が変わる可能性があります。したがって、合計は実際には現在のスワップ合計です。 C++では、このデータは次のようにして照会できます。
xsw_usage vmusage = {0};
size_t size = sizeof(vmusage);
if( sysctlbyname("vm.swapusage", &vmusage, &size, NULL, 0)!=0 )
{
perror( "unable to get swap usage by calling sysctlbyname(\"vm.swapusage\",...)" );
}
Sysctl.hで宣言されている "xsw_usage"は文書化されていないようで、これらの値にアクセスするためのもっと移植性のある方法があると私は思う。
task_info
関数を使って現在のプロセスに関する統計を得ることができます。それはあなたのプロセスの現在の常駐サイズと現在の仮想サイズを含みます。
#include<mach/mach.h>
struct task_basic_info t_info;
mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
if (KERN_SUCCESS != task_info(mach_task_self(),
TASK_BASIC_INFO, (task_info_t)&t_info,
&t_info_count))
{
return -1;
}
// resident size is in t_info.resident_size;
// virtual size is in t_info.virtual_size;
あなたのシステムで利用可能な物理的なRAMの量は、次のようなsysctl
システム関数を使用して利用可能です。
#include <sys/types.h>
#include <sys/sysctl.h>
...
int mib[2];
int64_t physical_memory;
mib[0] = CTL_HW;
mib[1] = HW_MEMSIZE;
length = sizeof(int64_t);
sysctl(mib, 2, &physical_memory, &length, NULL, 0);
Host_statistics
システム関数から一般的なメモリ統計を取得できます。
#include <mach/vm_statistics.h>
#include <mach/mach_types.h>
#include <mach/mach_init.h>
#include <mach/mach_Host.h>
int main(int argc, const char * argv[]) {
vm_size_t page_size;
mach_port_t mach_port;
mach_msg_type_number_t count;
vm_statistics64_data_t vm_stats;
mach_port = mach_Host_self();
count = sizeof(vm_stats) / sizeof(natural_t);
if (KERN_SUCCESS == Host_page_size(mach_port, &page_size) &&
KERN_SUCCESS == Host_statistics64(mach_port, Host_VM_INFO,
(Host_info64_t)&vm_stats, &count))
{
long long free_memory = (int64_t)vm_stats.free_count * (int64_t)page_size;
long long used_memory = ((int64_t)vm_stats.active_count +
(int64_t)vm_stats.inactive_count +
(int64_t)vm_stats.wire_count) * (int64_t)page_size;
printf("free memory: %lld\nused memory: %lld\n", free_memory, used_memory);
}
return 0;
}
ここで注意すべきことは、Mac OS Xには5種類のメモリページがあるということです。それらは次のとおりです。
Mac OS Xが実際の空きメモリをほとんど表示しない場合があるからといって、すぐに使用できる状態になっていることを示す良い指標ではない場合があることに注意してください。
上記の「自分のプロセスが現在使用している仮想メモリ」を参照してください。同じコードが適用されます。
Linuxでは、この情報は/ procファイルシステムにあります。各Linuxディストリビューションが少なくとも1つの重要なファイルをカスタマイズしているように見えるので、私は使用されているテキストファイルフォーマットの大ファンではありません。 'ps'の元になっているところをちょっと見ると、混乱が明らかになります。
しかし、ここであなたが求める情報を見つける場所です:
/proc/meminfo には、あなたが求めるシステム全体の情報の大部分が含まれています。これは私のシステムではこんな感じです。 MemTotal 、 MemFree 、 SwapTotal 、に興味があると思います。 /] SwapFree :
Anderson cxc # more /proc/meminfo
MemTotal: 4083948 kB
MemFree: 2198520 kB
Buffers: 82080 kB
Cached: 1141460 kB
SwapCached: 0 kB
Active: 1137960 kB
Inactive: 608588 kB
HighTotal: 3276672 kB
HighFree: 1607744 kB
LowTotal: 807276 kB
LowFree: 590776 kB
SwapTotal: 2096440 kB
SwapFree: 2096440 kB
Dirty: 32 kB
Writeback: 0 kB
AnonPages: 523252 kB
Mapped: 93560 kB
Slab: 52880 kB
SReclaimable: 24652 kB
SUnreclaim: 28228 kB
PageTables: 2284 kB
NFS_Unstable: 0 kB
Bounce: 0 kB
CommitLimit: 4138412 kB
Committed_AS: 1845072 kB
VmallocTotal: 118776 kB
VmallocUsed: 3964 kB
VmallocChunk: 112860 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
Hugepagesize: 2048 kB
CPU使用率のために、あなたは少し仕事をしなければなりません。 Linuxはシステム起動後の全体的なCPU使用率を利用可能にします。これはおそらくあなたが興味を持っているものではないでしょう。もしあなたが最後の1秒間、すなわち10秒間のCPU使用率が何であるか知りたいのなら、あなたは情報を問い合わせそしてそれをあなた自身で計算する必要があります。
この情報は/proc/stat にあります。これについては http://www.linuxhowtos.org/System/procstatで詳しく説明されています。 htm ;これが私の4コアボックスでの外観です。
Anderson cxc # more /proc/stat
cpu 2329889 0 2364567 1063530460 9034 9463 96111 0
cpu0 572526 0 636532 265864398 2928 1621 6899 0
cpu1 590441 0 531079 265949732 4763 351 8522 0
cpu2 562983 0 645163 265796890 682 7490 71650 0
cpu3 603938 0 551790 265919440 660 0 9040 0
intr 37124247
ctxt 50795173133
btime 1218807985
processes 116889
procs_running 1
procs_blocked 0
最初に、システムで利用可能なCPU(またはプロセッサ、またはプロセッシングコア)の数を決定する必要があります。これを行うには、 'cpuN'エントリの数を数えます。Nは0から始まり増加します。 cpuN行の組み合わせである 'cpu'行を数えないでください。私の例では、cpu0からcpu3まで、合計4つのプロセッサを見ることができます。これからは、cpu0..cpu3を無視して、 'cpu'行にだけ焦点を合わせることができます。
次に、これらの行の4番目の数値がアイドル時間の尺度であることを知っておく必要があります。したがって、「cpu」行の4番目の数値は、ブート時以降のすべてのプロセッサの合計アイドル時間です。この時間はLinuxの "jiffies"で測定され、それぞれ1/100秒です。
しかし、あなたは総アイドル時間を気にする必要はありません。あなたは与えられた期間、例えば最後の1秒間のアイドル時間を気にします。それを計算しなさい、あなたは2回、1秒間隔でこのファイルを読む必要がある。あなたはラインの4番目の値の差分をすることができる。たとえば、サンプルを取得して取得したとします。
cpu 2330047 0 2365006 1063853632 9035 9463 96114 0
それから1秒後にこのサンプルを入手します:
cpu 2330047 0 2365007 1063854028 9035 9463 96114 0
2つの数字を引くと、396の差が出ます。これは、最後の1.00秒のうち3.96秒間CPUがアイドル状態だったことを意味します。トリックは、もちろん、あなたはプロセッサの数で割る必要があるということです。 3.96/4 = 0.99で、アイドル率があります。 99%アイドル、1%ビジー。
私のコードでは、私は360エントリのリングバッファを持っていて、私は毎秒このファイルを読んでいます。これにより、1秒、10秒など、最大1時間までのCPU使用率をすばやく計算できます。
プロセス固有の情報については、/proc/pid を調べる必要があります。あなたのpidを気にしないのであれば、/ proc/selfを見ることができます。
あなたのプロセスが使用しているCPUは/proc/self/stat にあります。これは単一行からなる奇妙に見えるファイルです。例えば:
19340 (whatever) S 19115 19115 3084 34816 19115 4202752 118200 607 0 0 770 384 2
7 20 0 77 0 266764385 692477952 105074 4294967295 134512640 146462952 321468364
8 3214683328 4294960144 0 2147221247 268439552 1276 4294967295 0 0 17 0 0 0 0
ここで重要なデータは13番目と14番目のトークン(ここでは0と770)です。 13番目のトークンはプロセスがユーザーモードで実行したjiffの数であり、14番目はプロセスがカーネルモードで実行したjiffの数です。この2つを足し合わせると、その合計CPU使用率がわかります。
繰り返しになりますが、このファイルを定期的にサンプリングして、差分を計算し、プロセスのCPU使用率を経時的に判断する必要があります。
編集:プロセスのCPU使用率を計算するときは、1)プロセス内のスレッド数、2)システム内のプロセッサ数を考慮する必要があることを忘れないでください。たとえば、シングルスレッドプロセスがCPUの25%しか使用していない場合、それは良いことも悪いこともあります。シングルプロセッサシステムでは良いが、4プロセッサシステムでは悪い。これは、プロセスが絶えず実行されており、使用可能なCPUサイクルの100%を使用していることを意味します。
プロセス固有のメモリ情報については、/ proc/self/statusを見てください。これは次のようになります。
Name: whatever
State: S (sleeping)
Tgid: 19340
Pid: 19340
PPid: 19115
TracerPid: 0
Uid: 0 0 0 0
Gid: 0 0 0 0
FDSize: 256
Groups: 0 1 2 3 4 6 10 11 20 26 27
VmPeak: 676252 kB
VmSize: 651352 kB
VmLck: 0 kB
VmHWM: 420300 kB
VmRSS: 420296 kB
VmData: 581028 kB
VmStk: 112 kB
VmExe: 11672 kB
VmLib: 76608 kB
VmPTE: 1244 kB
Threads: 77
SigQ: 0/36864
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: fffffffe7ffbfeff
SigIgn: 0000000010001000
SigCgt: 20000001800004fc
CapInh: 0000000000000000
CapPrm: 00000000ffffffff
CapEff: 00000000fffffeff
Cpus_allowed: 0f
Mems_allowed: 1
voluntary_ctxt_switches: 6518
nonvoluntary_ctxt_switches: 6598
'Vm'で始まるエントリは興味深いものです。
私がよくわからない唯一の項目は現在私のプロセスで使用されているSwapspace です。これが利用可能かどうかはわかりません。
ウィンドウズでは、以下のコードでCPU使用率を得ることができます:
#include <windows.h>
#include <stdio.h>
//------------------------------------------------------------------------------------------------------------------
// Prototype(s)...
//------------------------------------------------------------------------------------------------------------------
CHAR cpuusage(void);
//-----------------------------------------------------
typedef BOOL ( __stdcall * pfnGetSystemTimes)( LPFILETIME lpIdleTime, LPFILETIME lpKernelTime, LPFILETIME lpUserTime );
static pfnGetSystemTimes s_pfnGetSystemTimes = NULL;
static HMODULE s_hKernel = NULL;
//-----------------------------------------------------
void GetSystemTimesAddress()
{
if( s_hKernel == NULL )
{
s_hKernel = LoadLibrary( L"Kernel32.dll" );
if( s_hKernel != NULL )
{
s_pfnGetSystemTimes = (pfnGetSystemTimes)GetProcAddress( s_hKernel, "GetSystemTimes" );
if( s_pfnGetSystemTimes == NULL )
{
FreeLibrary( s_hKernel ); s_hKernel = NULL;
}
}
}
}
//----------------------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------------------
// cpuusage(void)
// ==============
// Return a CHAR value in the range 0 - 100 representing actual CPU usage in percent.
//----------------------------------------------------------------------------------------------------------------
CHAR cpuusage()
{
FILETIME ft_sys_idle;
FILETIME ft_sys_kernel;
FILETIME ft_sys_user;
ULARGE_INTEGER ul_sys_idle;
ULARGE_INTEGER ul_sys_kernel;
ULARGE_INTEGER ul_sys_user;
static ULARGE_INTEGER ul_sys_idle_old;
static ULARGE_INTEGER ul_sys_kernel_old;
static ULARGE_INTEGER ul_sys_user_old;
CHAR usage = 0;
// we cannot directly use GetSystemTimes on C language
/* add this line :: pfnGetSystemTimes */
s_pfnGetSystemTimes(&ft_sys_idle, /* System idle time */
&ft_sys_kernel, /* system kernel time */
&ft_sys_user); /* System user time */
CopyMemory(&ul_sys_idle , &ft_sys_idle , sizeof(FILETIME)); // Could been optimized away...
CopyMemory(&ul_sys_kernel, &ft_sys_kernel, sizeof(FILETIME)); // Could been optimized away...
CopyMemory(&ul_sys_user , &ft_sys_user , sizeof(FILETIME)); // Could been optimized away...
usage =
(
(
(
(
(ul_sys_kernel.QuadPart - ul_sys_kernel_old.QuadPart)+
(ul_sys_user.QuadPart - ul_sys_user_old.QuadPart)
)
-
(ul_sys_idle.QuadPart-ul_sys_idle_old.QuadPart)
)
*
(100)
)
/
(
(ul_sys_kernel.QuadPart - ul_sys_kernel_old.QuadPart)+
(ul_sys_user.QuadPart - ul_sys_user_old.QuadPart)
)
);
ul_sys_idle_old.QuadPart = ul_sys_idle.QuadPart;
ul_sys_user_old.QuadPart = ul_sys_user.QuadPart;
ul_sys_kernel_old.QuadPart = ul_sys_kernel.QuadPart;
return usage;
}
//------------------------------------------------------------------------------------------------------------------
// Entry point
//------------------------------------------------------------------------------------------------------------------
int main(void)
{
int n;
GetSystemTimesAddress();
for(n=0;n<20;n++)
{
printf("CPU Usage: %3d%%\r",cpuusage());
Sleep(2000);
}
printf("\n");
return 0;
}
メモリとロード番号を読みやすくする方法は、 sysinfo
呼び出し です。
#include <sys/sysinfo.h>
int sysinfo(struct sysinfo *info);
Until Linux 2.3.16, sysinfo() used to return information in the
following structure:
struct sysinfo {
long uptime; /* Seconds since boot */
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
unsigned long totalram; /* Total usable main memory size */
unsigned long freeram; /* Available memory size */
unsigned long sharedram; /* Amount of shared memory */
unsigned long bufferram; /* Memory used by buffers */
unsigned long totalswap; /* Total swap space size */
unsigned long freeswap; /* swap space still available */
unsigned short procs; /* Number of current processes */
char _f[22]; /* Pads structure to 64 bytes */
};
and the sizes were given in bytes.
Since Linux 2.3.23 (i386), 2.3.48 (all architectures) the structure
is:
struct sysinfo {
long uptime; /* Seconds since boot */
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
unsigned long totalram; /* Total usable main memory size */
unsigned long freeram; /* Available memory size */
unsigned long sharedram; /* Amount of shared memory */
unsigned long bufferram; /* Memory used by buffers */
unsigned long totalswap; /* Total swap space size */
unsigned long freeswap; /* swap space still available */
unsigned short procs; /* Number of current processes */
unsigned long totalhigh; /* Total high memory size */
unsigned long freehigh; /* Available high memory size */
unsigned int mem_unit; /* Memory unit size in bytes */
char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding to 64 bytes */
};
and the sizes are given as multiples of mem_unit bytes.
これは「コードのウィキページ」のようなものですので、QNXナレッジベースからコードを追加したいと思います(注:これは私の作業ではありませんが、確認したところ、システム上で問題なく動作します)。
CPU使用率を%で表示する方法: http://www.qnx.com/support/knowledgebase.html?id=50130000000P9b5
#include <atomic.h>
#include <libc.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/iofunc.h>
#include <sys/neutrino.h>
#include <sys/resmgr.h>
#include <sys/syspage.h>
#include <unistd.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/debug.h>
#include <sys/procfs.h>
#include <sys/syspage.h>
#include <sys/neutrino.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
#include <devctl.h>
#include <errno.h>
#define MAX_CPUS 32
static float Loads[MAX_CPUS];
static _uint64 LastSutime[MAX_CPUS];
static _uint64 LastNsec[MAX_CPUS];
static int ProcFd = -1;
static int NumCpus = 0;
int find_ncpus(void) {
return NumCpus;
}
int get_cpu(int cpu) {
int ret;
ret = (int)Loads[ cpu % MAX_CPUS ];
ret = max(0,ret);
ret = min(100,ret);
return( ret );
}
static _uint64 nanoseconds( void ) {
_uint64 sec, usec;
struct timeval tval;
gettimeofday( &tval, NULL );
sec = tval.tv_sec;
usec = tval.tv_usec;
return( ( ( sec * 1000000 ) + usec ) * 1000 );
}
int sample_cpus( void ) {
int i;
debug_thread_t debug_data;
_uint64 current_nsec, sutime_delta, time_delta;
memset( &debug_data, 0, sizeof( debug_data ) );
for( i=0; i<NumCpus; i++ ) {
/* Get the sutime of the idle thread #i+1 */
debug_data.tid = i + 1;
devctl( ProcFd, DCMD_PROC_TIDSTATUS,
&debug_data, sizeof( debug_data ), NULL );
/* Get the current time */
current_nsec = nanoseconds();
/* Get the deltas between now and the last samples */
sutime_delta = debug_data.sutime - LastSutime[i];
time_delta = current_nsec - LastNsec[i];
/* Figure out the load */
Loads[i] = 100.0 - ( (float)( sutime_delta * 100 ) / (float)time_delta );
/* Flat out strange rounding issues. */
if( Loads[i] < 0 ) {
Loads[i] = 0;
}
/* Keep these for reference in the next cycle */
LastNsec[i] = current_nsec;
LastSutime[i] = debug_data.sutime;
}
return EOK;
}
int init_cpu( void ) {
int i;
debug_thread_t debug_data;
memset( &debug_data, 0, sizeof( debug_data ) );
/* Open a connection to proc to talk over.*/
ProcFd = open( "/proc/1/as", O_RDONLY );
if( ProcFd == -1 ) {
fprintf( stderr, "pload: Unable to access procnto: %s\n",strerror( errno ) );
fflush( stderr );
return -1;
}
i = fcntl(ProcFd,F_GETFD);
if(i != -1){
i |= FD_CLOEXEC;
if(fcntl(ProcFd,F_SETFD,i) != -1){
/* Grab this value */
NumCpus = _syspage_ptr->num_cpu;
/* Get a starting point for the comparisons */
for( i=0; i<NumCpus; i++ ) {
/*
* the sutime of idle thread is how much
* time that thread has been using, we can compare this
* against how much time has passed to get an idea of the
* load on the system.
*/
debug_data.tid = i + 1;
devctl( ProcFd, DCMD_PROC_TIDSTATUS, &debug_data, sizeof( debug_data ), NULL );
LastSutime[i] = debug_data.sutime;
LastNsec[i] = nanoseconds();
}
return(EOK);
}
}
close(ProcFd);
return(-1);
}
void close_cpu(void){
if(ProcFd != -1){
close(ProcFd);
ProcFd = -1;
}
}
int main(int argc, char* argv[]){
int i,j;
init_cpu();
printf("System has: %d CPUs\n", NumCpus);
for(i=0; i<20; i++) {
sample_cpus();
for(j=0; j<NumCpus;j++)
printf("CPU #%d: %f\n", j, Loads[j]);
sleep(1);
}
close_cpu();
}
空き(!)メモリを取得する方法: http://www.qnx.com/support/knowledgebase.html?id=50130000000mlbx
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <err.h>
#include <sys/stat.h>
#include <sys/types.h>
int main( int argc, char *argv[] ){
struct stat statbuf;
paddr_t freemem;
stat( "/proc", &statbuf );
freemem = (paddr_t)statbuf.st_size;
printf( "Free memory: %d bytes\n", freemem );
printf( "Free memory: %d KB\n", freemem / 1024 );
printf( "Free memory: %d MB\n", freemem / ( 1024 * 1024 ) );
return 0;
}
Mac OS X - CPU
全体的なCPU使用率
From MacOS Xのシステム情報を取得しますか? :
#include <mach/mach_init.h>
#include <mach/mach_error.h>
#include <mach/mach_Host.h>
#include <mach/vm_map.h>
static unsigned long long _previousTotalTicks = 0;
static unsigned long long _previousIdleTicks = 0;
// Returns 1.0f for "CPU fully pinned", 0.0f for "CPU idle", or somewhere in between
// You'll need to call this at regular intervals, since it measures the load between
// the previous call and the current one.
float GetCPULoad()
{
Host_cpu_load_info_data_t cpuinfo;
mach_msg_type_number_t count = Host_CPU_LOAD_INFO_COUNT;
if (Host_statistics(mach_Host_self(), Host_CPU_LOAD_INFO, (Host_info_t)&cpuinfo, &count) == KERN_SUCCESS)
{
unsigned long long totalTicks = 0;
for(int i=0; i<CPU_STATE_MAX; i++) totalTicks += cpuinfo.cpu_ticks[i];
return CalculateCPULoad(cpuinfo.cpu_ticks[CPU_STATE_IDLE], totalTicks);
}
else return -1.0f;
}
float CalculateCPULoad(unsigned long long idleTicks, unsigned long long totalTicks)
{
unsigned long long totalTicksSinceLastTime = totalTicks-_previousTotalTicks;
unsigned long long idleTicksSinceLastTime = idleTicks-_previousIdleTicks;
float ret = 1.0f-((totalTicksSinceLastTime > 0) ? ((float)idleTicksSinceLastTime)/totalTicksSinceLastTime : 0);
_previousTotalTicks = totalTicks;
_previousIdleTicks = idleTicks;
return ret;
}
Linuxの場合/ proc/self/statmを使用して、主要なプロセスメモリ情報を含む1行の数字を取得することもできます。これは、proc/self/statusから取得する場合の報告された情報の長いリストを調べるよりも処理が早い方法です。
http://man7.org/linux/man-pages/man5/proc.5.html を参照してください。
/proc/[pid]/statm
Provides information about memory usage, measured in pages.
The columns are:
size (1) total program size
(same as VmSize in /proc/[pid]/status)
resident (2) resident set size
(same as VmRSS in /proc/[pid]/status)
shared (3) number of resident shared pages (i.e., backed by a file)
(same as RssFile+RssShmem in /proc/[pid]/status)
text (4) text (code)
lib (5) library (unused since Linux 2.6; always 0)
data (6) data + stack
dt (7) dirty pages (unused since Linux 2.6; always 0)
私のC++プロジェクトでは次のコードを使用しましたが、うまくいきました。
static HANDLE self;
static int numProcessors;
SYSTEM_INFO sysInfo;
double percent;
numProcessors = sysInfo.dwNumberOfProcessors;
//Getting system times information
FILETIME SysidleTime;
FILETIME SyskernelTime;
FILETIME SysuserTime;
ULARGE_INTEGER SyskernelTimeInt, SysuserTimeInt;
GetSystemTimes(&SysidleTime, &SyskernelTime, &SysuserTime);
memcpy(&SyskernelTimeInt, &SyskernelTime, sizeof(FILETIME));
memcpy(&SysuserTimeInt, &SysuserTime, sizeof(FILETIME));
__int64 denomenator = SysuserTimeInt.QuadPart + SyskernelTimeInt.QuadPart;
//Getting process times information
FILETIME ProccreationTime, ProcexitTime, ProcKernelTime, ProcUserTime;
ULARGE_INTEGER ProccreationTimeInt, ProcexitTimeInt, ProcKernelTimeInt, ProcUserTimeInt;
GetProcessTimes(self, &ProccreationTime, &ProcexitTime, &ProcKernelTime, &ProcUserTime);
memcpy(&ProcKernelTimeInt, &ProcKernelTime, sizeof(FILETIME));
memcpy(&ProcUserTimeInt, &ProcUserTime, sizeof(FILETIME));
__int64 numerator = ProcUserTimeInt.QuadPart + ProcKernelTimeInt.QuadPart;
//QuadPart represents a 64-bit signed integer (ULARGE_INTEGER)
percent = 100*(numerator/denomenator);