как определить потребление ресурсов процессора и памяти внутри процесса?

<p>однажды у меня была задача определить следующие параметры производительности внутри работающего приложения:</p><ul> <li>общая доступная виртуальная память</li> <li>виртуальная память в настоящее время используется</li> <li>виртуальная память, используемая в настоящее время моим процессом <hr></li> <li>всего ram доступно</li> <li>ram в настоящее время используется</li> <li>ram в настоящее время используется моим процессом <hr></li> <li>% cpu в настоящее время используется</li> <li>% cpu в настоящее время используется моим процессом</li> </ul><p>код должен был работать на windows и linux. несмотря на то, что это стандартная задача, поиск необходимой информации в руководствах (win32 api, gnu docs), а также в интернете занял у меня несколько дней, потому что там слишком много неполных/неправильных/устаревших информацию по этой теме можно найти там.</p><p>чтобы избавить других от подобных неприятностей, я подумал, что было бы неплохо собрать всю разбросанную информацию, а также то, что я нашел методом проб и ошибок здесь, в одном месте.</p>

<h2>windows</h2><p>некоторые из приведенных выше значений легко доступны из соответствующего api-интерфейса win32, я просто перечислю их здесь для полноты. другие, однако, должны быть получены из библиотеки performance data helper (pdh), которая немного "не интуитивна" и требует много трудных проб и ошибок, чтобы приступить к работе. (по крайней мере, это заняло у меня довольно много времени, возможно, я был немного глупым ...)</p><p>примечание: для ясности вся проверка ошибок была исключена из следующего кода. проверьте коды возврата ...!</p><p><br></p><ul> <li> <p>общая виртуальная память:</p> <pre><code>#include "windows.h" memorystatusex meminfo; meminfo.dwlength = sizeof(memorystatusex); globalmemorystatusex(&meminfo); dwordlong totalvirtualmem = meminfo.ulltotalpagefile; </code></pre> <p>примечание. название "totalpagefile" вводит в заблуждение. на самом деле этот параметр дает "размер виртуальной памяти", который представляет собой размер файла подкачки плюс установленное озу.</p> </li> <li> <p>виртуальная память в настоящее время используется:</p> <p>тот же код, что и в "всего виртуальной памяти", а затем</p> <pre><code>dwordlong virtualmemused = meminfo.ulltotalpagefile - meminfo.ullavailpagefile; </code></pre></li> <li> <p>виртуальная память, используемая в настоящее время текущим процессом:</p> <pre><code>#include "windows.h" #include "psapi.h" process\_memory\_counters\_ex pmc; getprocessmemoryinfo(getcurrentprocess(), &pmc, sizeof(pmc)); size\_t virtualmemusedbyme = pmc.privateusage; </code></pre></li> </ul><p><br> <br></p><ul> <li> <p>общая физическая память (озу):</p> <p>тот же код, что и в "всего виртуальной памяти", а затем</p> <pre><code>dwordlong totalphysmem = meminfo.ulltotalphys; </code></pre></li> <li> <p>физическая память, используемая в настоящее время:</p> <pre><code>same code as in "total virtual memory" and then dwordlong physmemused = meminfo.ulltotalphys - meminfo.ullavailphys; </code></pre></li> <li> <p>физическая память, используемая в настоящее время текущим процессом:</p> <p>тот же код, что и в "виртуальной памяти, используемой текущим процессом", а затем</p> <pre><code>size\_t physmemusedbyme = pmc.workingsetsize; </code></pre></li> </ul><p><br> <br></p><ul> <li> <p>процессор, используемый в настоящее время:</p> <pre><code>#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; } </code></pre></li> <li> <p>процессор, используемый в настоящее время текущим процессом:</p> <pre><code>#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; } </code></pre></li> </ul><hr><h2>linux</h2><p>в linux выбор, который на первый взгляд казался очевидным, заключался в использовании api-интерфейсов posix, таких как <code>getrusage()</code> и т.д. я потратил некоторое время, пытаясь заставить это работать, но никогда не получал значимых значений. когда я наконец проверил исходные коды ядра, я обнаружил, что эти api еще не полностью реализованы в ядре linux 2.6 !?</p><p>в конце концов я получил все значения с помощью комбинации чтения псевдофайловой системы <code>/proc</code> и вызовов ядра.</p><ul> <li> <p>общая виртуальная память:</p> <pre><code>#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; </code></pre></li> <li> <p>виртуальная память в настоящее время используется:</p> <p>тот же код, что и в "всего виртуальной памяти", а затем</p> <pre><code>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; </code></pre></li> <li> <p>виртуальная память, используемая в настоящее время текущим процессом:</p> <pre><code>#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; } </code></pre></li> </ul><p><br> <br></p><ul> <li> <p>общая физическая память (озу):</p> <p>тот же код, что и в "всего виртуальной памяти", а затем</p> <pre><code>long long totalphysmem = meminfo.totalram; //multiply in next statement to avoid int overflow on right hand side... totalphysmem *= meminfo.mem\_unit; </code></pre></li> <li> <p>физическая память, используемая в настоящее время:</p> <p>тот же код, что и в "всего виртуальной памяти", а затем</p> <pre><code>long long physmemused = meminfo.totalram - meminfo.freeram; //multiply in next statement to avoid int overflow on right hand side... physmemused *= meminfo.mem\_unit; </code></pre></li> <li> <p>физическая память, используемая в настоящее время текущим процессом:</p> <p>измените getvalue () в "виртуальной памяти, используемой текущим процессом" следующим образом:</p> <pre><code>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; } </code></pre></li> </ul><p><br> <br></p><ul> <li> <p>процессор, используемый в настоящее время:</p> <pre><code>#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; } </code></pre></li> <li> <p>процессор, используемый в настоящее время текущим процессом:</p> <pre><code>#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(×ample); 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(×ample); 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; } </code></pre></li> </ul><hr><h2>todo: другие платформы</h2><p>я бы предположил, что часть кода linux также работает для unixes, за исключением частей, которые читают псевдофайловую систему/proc. возможно, в unix эти части можно заменить на <code>getrusage()</code> и подобные функции? если кто-то с ноу-хау unix может отредактировать этот ответ и заполнить детали ?!</p>

<h1>mac os x</h1><p>я надеялся найти подобную информацию и для mac os x. так как его здесь не было, я вышел и сам откопал его. вот некоторые из вещей, которые я нашел. если у кого-то есть какие-либо другие предложения, я бы хотел их услышать.</p><h2>общая виртуальная память</h2><p>это сложно на mac os x, потому что он не использует предустановленный раздел подкачки или файл, такой как linux. вот запись из документации apple:</p><blockquote> <p><strong>примечание:</strong> в отличие от большинства операционных систем на основе unix, mac os x не использует предварительно выделенный раздел подкачки для виртуальной памяти. вместо этого он использует все доступное пространство в загрузочном разделе компьютера.</p> </blockquote><p>итак, если вы хотите узнать, сколько виртуальной памяти еще доступно, вам необходимо получить размер корневого раздела. вы можете сделать это так:</p><pre><code>struct statfs stats; if (0 == statfs("/", &stats)) { myfreeswap = (uint64\_t)stats.f\_bsize * stats.f\_bfree; } </code></pre><h2>всего виртуальных в настоящее время используется</h2><p>вызов systcl с ключом "vm.swapusage" предоставляет интересную информацию об использовании подкачки:</p><pre><code>sysctl -n vm.swapusage vm.swapusage: total = 3072.00m used = 2511.78m free = 560.22m (encrypted) </code></pre><p>не то чтобы общее использование свопа, отображаемое здесь, может измениться, если потребуется больше свопа, как описано в разделе выше. таким образом, итоговая сумма - это <em> текущая </em> общая сумма свопинга. в c++ эти данные могут быть запрошены следующим образом:</p><pre><code>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\",...)" ); } </code></pre><p>обратите внимание, что "xsw\_usage", объявленный в sysctl.h, кажется не документированным, и я подозреваю, что существует более переносимый способ доступа к этим значениям.</p><h2>виртуальная память, используемая в настоящее время моим процессом</h2><p>вы можете получить статистику о вашем текущем процессе, используя функцию <code>task\_info</code>. это включает текущий размер резидента вашего процесса и текущий виртуальный размер.</p><pre><code>#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; </code></pre><h2>всего ram доступно</h2><p>количество физических ram, доступных в вашей системе, доступно с помощью системной функции <code>sysctl</code>, например:</p><pre><code>#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); </code></pre><h2>ram в настоящее время используется</h2><p>вы можете получить общую статистику памяти из системной функции <code>host\_statistics</code>.</p><pre><code>#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; } </code></pre><p>здесь следует отметить, что в mac os x существует пять типов страниц памяти:</p><ol> <li><strong>проводной</strong> страницы, которые заблокированы на месте и не могут быть заменены</li> <li><strong>активные</strong> страницы, которые загружаются в физическую память, и их было бы относительно трудно выгрузить</li> <li><strong>неактивные</strong> страницы, которые загружены в память, но не использовались в последнее время и могут вообще не понадобиться. это потенциальные кандидаты на обмен. эта память, вероятно, должна быть очищена.</li> <li><strong>кэшированные</strong> страницы, которые были как-то кэшированы, и которые, вероятно, могут быть легко использованы повторно. кэшированная память, вероятно, не потребует очистки. кэшированные страницы все еще могут быть реактивированы</li> <li><strong>бесплатно</strong> страницы, которые полностью бесплатны и готовы к использованию.</li> </ol><p>хорошо отметить, что только потому, что mac os x может показывать очень мало фактической свободной памяти время от времени, это может не быть хорошим показателем того, сколько готово использовать в короткие сроки.</p><h2>ram в настоящее время используется моим процессом</h2><p>см. "виртуальная память, используемая в настоящее время моим процессом" выше. тот же код применяется.</p>

<h1>linux</h1><p>в linux эта информация доступна в файловой системе/proc. я не большой поклонник используемого формата текстовых файлов, так как каждый дистрибутив linux, кажется, настраивает хотя бы один важный файл. беглый взгляд, как источник "ps" показывает беспорядок.</p><p>но вот где найти информацию, которую вы ищете:</p><p><strong>/proc/meminfo </strong> содержит большую часть всей информации, которую вы ищете. вот как это выглядит в моей системе; я думаю, что вы заинтересованы в <strong> memtotal </strong>, <strong> memfree </strong>, <strong> swaptotal </strong> и <strong> swapfree </strong>:</p><pre><code>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 </code></pre><p>для загрузки процессора вам нужно проделать небольшую работу. linux делает доступным общее использование процессора с момента запуска системы; это, вероятно, не то, что вас интересует. если вы хотите узнать, как загруженность процессора была в течение последней секунды или 10 секунд, то вам нужно запросить информацию и рассчитать ее самостоятельно.</p><p>информация доступна в <strong>/proc/stat </strong>, что довольно хорошо задокументировано на <a href="http://www.linuxhowtos.org/system/procstat.htm">http://www.linuxhowtos.org/system/ procstat.htm</a> ; вот как это выглядит на моей 4-х ядерной коробке:</p><pre><code>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 </code></pre><p>во-первых, вам необходимо определить, сколько процессоров (или процессоров, или процессорных ядер) доступно в системе. для этого подсчитайте количество записей "cpun", где n начинается с 0 и увеличивается. не считайте строку 'cpu', которая является комбинацией линий cpu. в моем примере вы можете увидеть cpu0 - cpu3, всего 4 процессора. отныне вы можете игнорировать cpu0..cpu3 и фокусироваться только на строке 'cpu'.</p><p>далее вам нужно знать, что четвертое число в этих строках является мерой времени простоя, и, таким образом, четвертое число в строке 'cpu' - это общее время простоя для всех процессоров с момента загрузки. это время измеряется в linux "jiffies", которые составляют 1/100 секунды каждый.</p><p>но вас не волнует общее время простоя; вы заботитесь о времени простоя в данный период, например, в последнюю секунду. подсчитайте, что вам нужно прочитать этот файл дважды, с интервалом в 1 секунду. затем вы можете сделать разность четвертого значения строки. например, если вы берете образец и получаете:</p><pre><code>cpu 2330047 0 2365006 1063853632 9035 9463 96114 0 </code></pre><p>затем через секунду вы получите этот образец:</p><pre><code>cpu 2330047 0 2365007 1063854028 9035 9463 96114 0 </code></pre><p>вычтите два числа, и вы получите разность 396, что означает, что ваш процессор простаивал 3,96 секунды из последних 1,00 секунды. хитрость, конечно, в том, что вам нужно разделить количество процессоров. 3,96/4 = 0,99, и ваш процент простоя; 99% простаивают и 1% заняты.</p><p>в моем коде у меня есть кольцевой буфер на 360 записей, и я читаю этот файл каждую секунду. это позволяет мне быстро рассчитать загрузку процессора за 1 секунду, 10 секунд и т.д. вплоть до 1 часа.</p><p>информацию о конкретном процессе вы можете найти в <strong>/proc/pid </strong>; если вам все равно, ваш pid, вы можете посмотреть в/proc/self.</p><p>процессор, используемый вашим процессом, доступен в <strong>/proc/self/stat </strong>. это странно выглядящий файл, состоящий из одной строки; например:</p><pre><code>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 </code></pre><p>важными данными здесь являются 13-й и 14-й токены (0 и 770 здесь). 13-й токен - это количество jiffies, которые процесс выполнил в пользовательском режиме, а 14-й - количество jiffies, которые процесс выполнил в режиме ядра. добавьте их вместе, и вы получите полную загрузку процессора.</p><p>опять же, вам придется периодически выбирать этот файл и вычислять разницу, чтобы определить загрузку цп процесса с течением времени.</p><p><strong> изменить: </strong> помните, что когда вы вычисляете загрузку цп вашего процесса, вы должны учитывать 1) количество потоков в вашем процессе и 2) количество процессоров в системе. например, если ваш однопоточный процесс использует только 25% цп, это может быть хорошо или плохо. хорошо для однопроцессорной системы, но плохо для четырехпроцессорной; это означает, что ваш процесс работает постоянно и использует 100% доступных ему циклов цп.</p><p>для получения информации о памяти, относящейся к процессу, вы должны посмотреть на/proc/self/status, который выглядит следующим образом:</p><pre><code>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 </code></pre><p>записи, начинающиеся с 'vm', являются интересными:</p><ul> <li><strong> vmpeak </strong> - это максимальное пространство виртуальной памяти, используемое процессом, в кб (1024 байта).</li> <li><strong> vmsize </strong> - текущее пространство виртуальной памяти, используемое процессом, в килобайтах. в моем примере он довольно большой: 651 352 кб или около 636 мегабайт.</li> <li><strong> vmrss </strong> - это объем памяти, который был отображен в адресное пространство процесса, или размер его резидентного набора. это существенно меньше (420 296 кб, или около 410 мегабайт). разница: моя программа сопоставила 636 мб с помощью mmap (), но получила доступ только к 410 мб, и, таким образом, ей было выделено только 410 мб страниц.</li> </ul><p>единственный элемент, в котором я не уверен, - это <strong> пространство подкачки, используемое в настоящее время моим процессом </strong>. я не знаю, доступно ли это.</p>

<p><strong>в windows вы можете получить информацию об использовании процессора по коду ниже:</strong></p><pre><code>#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; } </code></pre>

<h1>linux</h1><p>портативный способ чтения памяти и номеров загрузки - <a href="http://man7.org/linux/man-pages/man2/sysinfo.2.html"><code>sysinfo</code> call</a> </p><h2>использование</h2><pre><code> #include <sys/sysinfo.h> int sysinfo(struct sysinfo *info); </code></pre><h2>описание</h2><pre><code> 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. </code></pre>

<h1>qnx</h1><p>поскольку это похоже на "вики-страницу кода", я хочу добавить код из базы знаний qnx (примечание: это не моя работа, но я проверил ее и она отлично работает в моей системе):</p><p>как получить использование процессора в%: <a href="http://www.qnx.com/support/knowledgebase.html?id=50130000000p9b5">http://www.qnx.com/support/knowledgebase.html?id=50130000000p9b5</a> </p><pre><code>#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(); } </code></pre><p>как получить бесплатную (!) память: <a href="http://www.qnx.com/support/knowledgebase.html?id=50130000000mlbx">http://www.qnx.com/support/knowledgebase.html?id=50130000000mlbx</a> </p><pre><code>#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; } </code></pre>

<p><strong> mac os x - процессор </strong></p><p>общее использование процессора:</p><p>от <a href="https://stackoverflow.com/questions/8736713/retrieve-system-information-on-macos-x">получить системную информацию на macos x?</a> :</p><pre><code>#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; } </code></pre>

<p>для linux вы также можете использовать/proc/self/statm, чтобы получить одну строку чисел, содержащую ключевую информацию о памяти процесса, которая быстрее обрабатывается, чем просматривает длинный список сообщаемой информации, которую вы получаете из proc/self/status</p><p>смотрите <a href="http://man7.org/linux/man-pages/man5/proc.5.html">http://man7.org/linux/man-pages/man5/proc.5.html</a> </p><pre><code> /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) </code></pre>

<p>я использовал следующий код в своем проекте c++, и он работал нормально:</p><pre><code>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); </code></pre>