sprof(1) General Commands Manual sprof(1)

sprof - پروفایل‌بندی و خواندن داده‌های پروفایل اشیاء اشتراکی

sprof [گزینه]... shared-object-path [profile-data-path]

دستور sprof خلاصه‌ای از داده‌های پروفایل شیء اشتراکی (کتابخانه اشتراکی) مشخص‌شده در نخستین آرگومان خط فرمان را نمایش می‌دهد. این خلاصه پروفایل با استفاده از داده‌های پروفایل‌سازی که از پیش تولید شده و در آرگومان خط فرمان دوم (اختیاری) مشخص می‌گردد، ایجاد می‌شود. اگر مسیر فایل داده‌های پروفایل حذف شود، sprof تلاش می‌کند با استفاده از soname شیء اشتراکی، آن را استنتاج کرده و در دایرکتوری جاری به دنبال فایلی با نام <soname>.profile بگردد.

گزینه‌های خط فرمان زیر نوع خروجی پروفایل تولیدشده را مشخص می‌کنند:

چاپ فهرستی از جفت‌مسیرهای فراخوانی برای رابط‌های صادرشده توسط شیء اشتراکی، همراه با تعداد دفعاتی که هر مسیر استفاده شده است.
تولید یک پروفایل تخت (Flat profile) از تمام توابع موجود در شیء تحت نظارت، همراه با تعداد فراخوانی‌ها و تیک‌ها.
تولید گراف فراخوانی (Call graph).

اگر هیچ‌یک از گزینه‌های بالا مشخص نشود، رفتار پیش‌فرض نمایش یک پروفایل تخت و یک گراف فراخوانی است.

گزینه‌های اضافی خط فرمان زیر نیز در دسترس هستند:

-?
نمایش خلاصه‌ای از گزینه‌ها و آرگومان‌های خط فرمان و خروج.
نمایش پیام کوتاه نحوه استفاده از دستور و خروج.
نمایش نسخه برنامه و خروج.

گنو (GNU).

مثال زیر نحوه استفاده از sprof را نشان می‌دهد. این مثال شامل یک برنامه اصلی است که دو تابع را در یک شیء اشتراکی فراخوانی می‌کند. نخست، کد برنامه اصلی:


$ cat prog.c
#include <stdlib.h>
void x1(void);
void x2(void);
int
main(int argc, char *argv[])
{
    x1();
    x2();
    exit(EXIT_SUCCESS);
}

توابع x1() و x2() در فایل منبع زیر تعریف شده‌اند که برای ساخت شیء اشتراکی به کار می‌رود:


$ cat libdemo.c
#include <unistd.h>
void
consumeCpu1(int lim)
{
    for (unsigned int j = 0; j < lim; j++)
	getppid();
}
void
x1(void) {
    for (unsigned int j = 0; j < 100; j++)
	consumeCpu1(200000);
}
void
consumeCpu2(int lim)
{
    for (unsigned int j = 0; j < lim; j++)
	getppid();
}
void
x2(void)
{
    for (unsigned int j = 0; j < 1000; j++)
	consumeCpu2(10000);
}

اکنون شیء اشتراکی را با نام واقعی libdemo.so.1.0.1 و با soname معادل libdemo.so.1 می‌سازیم:


$ cc -g -fPIC -shared -Wl,-soname,libdemo.so.1 \
        -o libdemo.so.1.0.1 libdemo.c

سپس پیوندهای نمادین را برای soname کتابخانه و نام پیونددهنده کتابخانه ایجاد می‌کنیم:


$ ln -sf libdemo.so.1.0.1 libdemo.so.1
$ ln -sf libdemo.so.1 libdemo.so

سپس برنامه اصلی را کامپایل کرده و آن را به شیء اشتراکی پیوند می‌دهیم، و در ادامه وابستگی‌های پویای برنامه را فهرست می‌کنیم:


$ cc -g -o prog prog.c -L. -ldemo
$ ldd prog
	linux-vdso.so.1 =>  (0x00007fff86d66000)
	libdemo.so.1 => not found
	libc.so.6 => /lib64/libc.so.6 (0x00007fd4dc138000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fd4dc51f000)

به‌منظور دریافت اطلاعات پروفایل برای شیء اشتراکی، متغیر محیطی LD_PROFILE را با soname کتابخانه مقداردهی می‌کنیم:


$ export LD_PROFILE=libdemo.so.1

سپس متغیر محیطی LD_PROFILE_OUTPUT را با مسیر دایرکتوری که خروجی پروفایل باید در آن نوشته شود مشخص کرده و در صورت عدم وجود، آن دایرکتوری را ایجاد می‌کنیم:


$ export LD_PROFILE_OUTPUT=$(pwd)/prof_data
$ mkdir -p $LD_PROFILE_OUTPUT

متغیر LD_PROFILE باعث می‌شود در صورتی که فایل خروجی از قبل وجود داشته باشد، داده‌های پروفایل به انتهای آن پیوست (append) شوند؛ بنابراین مطمئن می‌شویم که هیچ داده پروفایل از قبل وجود نداشته باشد:


$ rm -f $LD_PROFILE_OUTPUT/$LD_PROFILE.profile

سپس برنامه را اجرا می‌کنیم تا خروجی پروفایل تولید شود؛ این خروجی در فایلی درون دایرکتوری مشخص‌شده در LD_PROFILE_OUTPUT نوشته می‌شود:


$ LD_LIBRARY_PATH=. ./prog
$ ls prof_data
libdemo.so.1.profile

سپس از گزینه sprof -p برای تولید پروفایل تخت به همراه تعداد فراخوانی‌ها و تیک‌ها استفاده می‌کنیم:


$ sprof -p libdemo.so.1 $LD_PROFILE_OUTPUT/libdemo.so.1.profile
Flat profile:
Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total
 time   seconds   seconds    calls  us/call  us/call  name
 60.00      0.06     0.06      100   600.00           consumeCpu1
 40.00      0.10     0.04     1000    40.00           consumeCpu2
  0.00      0.10     0.00        1     0.00           x1
  0.00      0.10     0.00        1     0.00           x2

گزینه sprof -q یک گراف فراخوانی تولید می‌کند:


$ sprof -q libdemo.so.1 $LD_PROFILE_OUTPUT/libdemo.so.1.profile
index % time    self  children    called     name
                0.00    0.00      100/100         x1 [1]
[0]    100.0    0.00    0.00      100         consumeCpu1 [0]
-----------------------------------------------
                0.00    0.00        1/1           <UNKNOWN>
[1]      0.0    0.00    0.00        1         x1 [1]
                0.00    0.00      100/100         consumeCpu1 [0]
-----------------------------------------------
                0.00    0.00     1000/1000        x2 [3]
[2]      0.0    0.00    0.00     1000         consumeCpu2 [2]
-----------------------------------------------
                0.00    0.00        1/1           <UNKNOWN>
[3]      0.0    0.00    0.00        1         x2 [3]
                0.00    0.00     1000/1000        consumeCpu2 [2]
-----------------------------------------------

در بالا و پایین، رشته‌های "<UNKNOWN>" نشان‌دهنده شناسه‌هایی هستند که خارج از شیء پروفایل‌شده قرار دارند (در این مثال، این موارد نمونه‌هایی از main() هستند).

گزینه sprof -c فهرستی از جفت‌های فراخوانی و تعداد رخدادهای آن‌ها را تولید می‌کند:


$ sprof -c libdemo.so.1 $LD_PROFILE_OUTPUT/libdemo.so.1.profile
<UNKNOWN>                  x1                                 1
x1                         consumeCpu1                      100
<UNKNOWN>                  x2                                 1
x2                         consumeCpu2                     1000

gprof(1), ldd(1), ld.so(8)

2024-06-15 Linux man-pages 6.9.1