memusage(1) دستورات عمومی کاربر memusage(1)

memusage - پروفایل‌سازی و بررسی مصرف حافظه یک برنامه

memusage [گزینه‌ها]... برنامه [گزینه‌های‌برنامه]...

دستور memusage یک اسکریپت بش (bash) است که مصرف حافظه یک برنامه مشخص‌شده توسط program را پروفایل‌سازی و بررسی می‌کند. این اسکریپت کتابخانه libmemusage.so را در محیط فراخواننده از طریق متغیر محیطی LD_PRELOAD (به ld.so(8) مراجعه کنید) از پیش بارگذاری می‌کند. کتابخانه libmemusage.so تخصیص حافظه را با رهگیری فراخوانی‌های توابع malloc(3)، calloc(3)، free(3) و realloc(3) ردیابی می‌کند؛ همچنین به‌صورت اختیاری، فراخوانی‌های توابع mmap(2)، mremap(2) و munmap(2) نیز می‌توانند رهگیری شوند.

دستور memusage می‌تواند داده‌های جمع‌آوری‌شده را به شکل متنی چاپ کند، یا می‌تواند با استفاده از memusagestat(1) (گزینه -p در ادامه را ببینید) یک فایل گرافیکی PNG شامل نمایش نموداری از داده‌های جمع‌آوری‌شده ایجاد نماید.

خط «خلاصه مصرف حافظه» (Memory usage summary) که در خروجی memusage نمایش داده می‌شود، شامل سه فیلد است:

مجموع حافظه هیپ (heap total)
مجموع آرگومان‌های size در تمام فراخوانی‌های malloc(3)، حاصل‌ضرب آرگومان‌ها (nmemb*size) در تمام فراخوانی‌های calloc(3) و مجموع آرگومان‌های length در تمام فراخوانی‌های mmap(2). در مورد realloc(3) و mremap(2)، اگر اندازه جدید یک تخصیص از اندازه قبلی بزرگ‌تر باشد، مجموع تمام این اختلاف‌ها (اندازه جدید منهای اندازه قبلی) اضافه می‌شود.
اوج مصرف هیپ (heap peak)
بیشینه تمام آرگومان‌های size در malloc(3)، تمام حاصل‌ضرب‌های nmemb*size در calloc(3)، تمام آرگومان‌های size در realloc(3)، آرگومان‌های length در mmap(2) و آرگومان‌های new_size در mremap(2).
اوج مصرف پشته (stack peak)
پیش از نخستین فراخوانی به هر تابع تحت نظارت، نشانی اشاره‌گر پشته (اشاره‌گر پشته پایه) ذخیره می‌شود. پس از هر فراخوانی تابع، نشانی واقعی اشاره‌گر پشته خوانده شده و اختلاف آن با اشاره‌گر پشته پایه محاسبه می‌گردد. بیشینه این اختلاف‌ها، اوج مصرف پشته (stack peak) خواهد بود.

بلافاصله پس از این خط خلاصه، یک جدول تعداد فراخوانی‌ها، مجموع حافظه تخصیص‌یافته یا آزادشده، و تعداد فراخوانی‌های ناموفق را برای هر یک از توابع رهگیری‌شده نشان می‌دهد. برای realloc(3) و mremap(2)، فیلد اضافی «nomove» بازتخصیص‌هایی را نشان می‌دهد که نشانی یک بلوک را تغییر داده‌اند، و فیلد اضافی «dec» بازتخصیص‌هایی را نشان می‌دهد که اندازه بلوک را کاهش داده‌اند. برای realloc(3)، فیلد اضافی «free» بازتخصیص‌هایی را نشان می‌دهد که باعث آزادسازی یک بلوک شده‌اند (یعنی اندازه بازتخصیص‌یافته 0 بوده است).

ردیف «realloc/total memory» در جدول خروجیِ memusage مواردی را که در آن‌ها از realloc(3) برای بازتخصیص یک بلوک حافظه به اندازه‌ای کوچک‌تر از اندازه قبلی استفاده شده است بازتاب نمی‌دهد. این موضوع می‌تواند باعث شود مجموع تمام خانه‌های «total memory» (به‌جز «free») بزرگ‌تر از خانه «free/total memory» باشد.

بخش «هیستوگرام برای اندازه‌های بلوک» تفکیکی از تخصیص‌های حافظه را در دسته‌بندی‌های مختلف اندازه (buckets) ارائه می‌دهد.

نام فایل برنامه‌ای که باید پروفایل‌سازی شود.
تولید تصویر گرافیکی PNG و ذخیره آن در file.
تولید فایل داده‌های باینری و ذخیره آن در file.
عدم بافر کردن خروجی.
جمع‌آوری تعداد size ورودی پیش از نوشتن آن‌ها در خروجی.
غیرفعال کردن نمونه‌برداری مبتنی بر تایمر (SIGPROF) از مقدار اشاره‌گر پشته.
ردیابی فراخوانی‌های mmap(2)، mremap(2) و munmap(2) علاوه بر توابع پیش‌فرض.
-?, --help
نمایش راهنما و خروج.
نمایش پیام کوتاه نحوه استفاده و خروج.
نمایش اطلاعات نسخه و خروج.
گزینه‌های زیر تنها هنگام تولید خروجی گرافیکی اعمال می‌شوند:
استفاده از زمان (به‌جای تعداد فراخوانی‌های توابع) به عنوان مقیاس محور X.
رسم نمودار مصرف کل حافظه نیز علاوه بر سایر موارد.
استفاده از name به عنوان عنوان نمودار.
تنظیم عرض نمودار به میزان size پیکسل.
تنظیم ارتفاع نمودار به میزان size پیکسل.

وضعیت خروج memusage برابر با وضعیت خروج برنامه پروفایل‌شده است.

برای گزارش اشکالات، ببینید: http://www.gnu.org/software/libc/bugs.html

در ادامه یک برنامه ساده آمده است که یک بلوک حافظه را در چرخه‌هایی که ابتدا به یک نقطه اوج می‌رسند بازتخصیص می‌دهد و سپس به‌صورت چرخه‌ای با اندازه‌های کوچک‌تر بازتخصیص داده و در نهایت به صفر بازمی‌گرداند. پس از کامپایل برنامه و اجرای دستورات زیر، نمودار مصرف حافظه برنامه را می‌توان در فایل memusage.png مشاهده کرد:


$ memusage --data=memusage.dat ./a.out
...
Memory usage summary: heap total: 45200, heap peak: 6440, stack peak: 224
        total calls  total memory  failed calls
 malloc|         1           400             0
realloc|        40         44800             0  (nomove:40, dec:19, free:0)
 calloc|         0             0             0
   free|         1           440
Histogram for block sizes:
  192-207             1   2% ================
...
 2192-2207            1   2% ================
 2240-2255            2   4% =================================
 2832-2847            2   4% =================================
 3440-3455            2   4% =================================
 4032-4047            2   4% =================================
 4640-4655            2   4% =================================
 5232-5247            2   4% =================================
 5840-5855            2   4% =================================
 6432-6447            1   2% ================
$ memusagestat memusage.dat memusage.png

#include <stdio.h>
#include <stdlib.h>
#define CYCLES 20
int
main(int argc, char *argv[])
{
    int i, j;
    size_t size;
    int *p;
    size = sizeof(*p) * 100;
    printf("malloc: %zu\n", size);
    p = malloc(size);
    for (i = 0; i < CYCLES; i++) {
        if (i < CYCLES / 2)
            j = i;
        else
            j--;
        size = sizeof(*p) * (j * 50 + 110);
        printf("realloc: %zu\n", size);
        p = realloc(p, size);
        size = sizeof(*p) * ((j + 1) * 150 + 110);
        printf("realloc: %zu\n", size);
        p = realloc(p, size);
    }
    free(p);
    exit(EXIT_SUCCESS);
}

memusagestat(1), mtrace(1), ld.so(8)

2024-06-15 Linux man-pages 6.9.1