Linux avp-ubu1 2.6.32-38-generic #83-Ubuntu SMP Wed Jan 4 11:12:07 UTC 2012 x86_64 GNU/Linux
Казалось бы очевидно (из man)
M Maximum resident set size of the process during its life‐
time, in Kilobytes.
Однако, значение, которое я увидел для тестируемой программы, выглядело каким-то несуразно большим.
Написал простой тест, который делает malloc(), memset() и потом free() и распечатал данные по памяти из /proc/self/status в разных точках этой программки.
/usr/bin/time maxresident оказался равен VmHWM * 4 (???) VmHWM: Peak resident set size ("high water mark").
(См. man 5 proc). В принципе если 'kB' после значения VmHWM это количество (в тысячах) 4Kbytes страниц, то похоже. Но (!) уж больно это VmHWM совпадает с количеством байт выделяемых malloc.
Что бы все это значило?
Вывод программки
avp@avp-ubu1:~/src/tst/sort$ gcc mem.c
avp@avp-ubu1:~/src/tst/sort$ /usr/bin/time ./a.out 4000000
VmPeak: 4000 kB
VmSize: 4000 kB
VmLck: 0 kB
VmHWM: 508 kB
VmRSS: 508 kB
VmData: 184 kB
VmStk: 88 kB
VmExe: 8 kB
VmLib: 1640 kB
VmPTE: 28 kB
start vmsize: 4000
VmPeak: 7912 kB
VmSize: 7912 kB
VmLck: 0 kB
VmHWM: 560 kB
VmRSS: 560 kB
VmData: 4096 kB
VmStk: 88 kB
VmExe: 8 kB
VmLib: 1640 kB
VmPTE: 32 kB
malloc 4000000 vmsize: 7912
VmPeak: 7912 kB
VmSize: 7912 kB
VmLck: 0 kB
VmHWM: 4464 kB
VmRSS: 4464 kB
VmData: 4096 kB
VmStk: 88 kB
VmExe: 8 kB
VmLib: 1640 kB
VmPTE: 36 kB
memset vmsize: 7912
VmPeak: 7912 kB
VmSize: 4004 kB
VmLck: 0 kB
VmHWM: 4468 kB
VmRSS: 556 kB
VmData: 188 kB
VmStk: 88 kB
VmExe: 8 kB
VmLib: 1640 kB
VmPTE: 28 kB
end vmsize: 4004
0.01user 0.00system 0:00.00elapsed 250%CPU (0avgtext+0avgdata 17872maxresident)k
0inputs+0outputs (0major+1157minor)pagefaults 0swaps
avp@avp-ubu1:~/src/tst/sort$
avp@avp-ubu1:~/src/tst/sort$
Просто обновил (через 2 недели), может быть кто-нибудь из новичков знает?
=== UPDATE ===
Возьмем простую программку
#include
int
main (int ac, char *av[])
{
char cmd[100];
struct rusage r;
getrusage(RUSAGE_SELF, &r);
printf("ru_maxrss: %ld
", r.ru_maxrss);
sprintf(cmd, "grep Vm /proc/%d/status", (int)getpid());
system(cmd);
getrusage(RUSAGE_SELF, &r);
printf("ru_maxrss: %ld
", r.ru_maxrss);
return puts("End") == EOF;
}
и запустим ее
avp@avp-xub11:hashcode$ ./a.out
ru_maxrss: 2544
VmPeak: 2112 kB
VmSize: 2024 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 284 kB
VmRSS: 284 kB
VmData: 32 kB
VmStk: 136 kB
VmExe: 4 kB
VmLib: 1824 kB
VmPTE: 16 kB
VmSwap: 0 kB
ru_maxrss: 2544
End
avp@avp-xub11:hashcode$
а теперь запустим ее же через /usr/bin/time
avp@avp-xub11:hashcode$ /usr/bin/time ./a.out
ru_maxrss: 280
VmPeak: 2112 kB
VmSize: 2024 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 280 kB
VmRSS: 280 kB
VmData: 32 kB
VmStk: 136 kB
VmExe: 4 kB
VmLib: 1824 kB
VmPTE: 16 kB
VmSwap: 0 kB
ru_maxrss: 280
End
0.00user 0.02system 0:00.07elapsed 30%CPU (0avgtext+0avgdata 840maxresident)k
0inputs+0outputs (0major+583minor)pagefaults 0swaps
avp@avp-xub11:hashcode$
В последнем запуске мы видим, что наш Maximum resident set size, полученный из getrusage() равен 280 и совпадает со значением VmRSS из /proc/PID/status.
Однако, в выводе /usr/bin/time мы видим 840. Вот и вопрос, почему???
Кстати, если кто-то обратил внимание, то в первом запуске getrusage() возвращает почему-то совсем другое число (не совпадающее ни с чем в /proc/PID/status ... ), но это уже другой вопрос.
Ответ
что такое maximum resident set size — объясняется вкратце здесь
разница в «показаниях» между тем, что выдаёт тестовая программа и тем, что выдаёт программа /usr/bin/time, запускающая тестовую программу, заключается в моменте «снятия показаний»
тестовая программа делает это в процессе своего выполнения, а /usr/bin/time — уже после завершения тестовой программы.
понятно, что в разные моменты времени динамически изменяющаяся величина, характеризующая процесс, может изменяться.
обновление
но столь кардинальное различие (в четыре раза) проистекает из ошибки в исходниках gnu/time
в дистрибутиве debian эта ошибка была исправлена коротким патчем
--- time-1.7.orig/time.c 2011-11-20 17:48:44.000000000 +0000
+++ time-1.7/time.c 2011-11-20 17:50:25.000000000 +0000
@@ -398,7 +398,7 @@
ptok ((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS (v));
break;
case 'M': /* Maximum resident set size. */
- fprintf (fp, "%lu", ptok ((UL) resp->ru.ru_maxrss));
+ fprintf (fp, "%lu", (UL) resp->ru.ru_maxrss);
break;
case 'O': /* Outputs. */
fprintf (fp, "%ld", resp->ru.ru_oublock);
Комментариев нет:
Отправить комментарий