GNU/Linux >> Znalost Linux >  >> Linux

Profilování aplikací pro Linux

V ideálním případě potřebuji aplikaci, která se připojí k procesu a zaznamenává pravidelné snímky:

  • Využití paměti
  • počet vláken
  • Využití CPU

Abyste mohli shromažďovat tento typ informací o vašem procesu, nepotřebujete v Linuxu profiler.

  1. Můžete použít top v dávkovém režimu. Běží v dávkovém režimu, dokud není zabit, nebo dokud není provedeno N iterací:

    top -b -p `pidof a.out`
    

    nebo

    top -b -p `pidof a.out` -n 100
    

    a dostanete toto:

    $ top -b -p `pidof a.out`
    
    top - 10:31:50 up 12 days, 19:08,  5 users,  load average: 0.02, 0.01, 0.02
    Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
    Cpu(s):  0.0%us,  0.0%sy,  0.0%ni,100.0%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
    Mem:  16330584k total,  2335024k used, 13995560k free,   241348k buffers
    Swap:  4194296k total,        0k used,  4194296k free,  1631880k cached
    
      PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    24402 SK        20   0 98.7m 1056  860 S 43.9  0.0   0:11.87 a.out
    
    
    top - 10:31:53 up 12 days, 19:08,  5 users,  load average: 0.02, 0.01, 0.02
    Tasks:   1 total,   0 running,   1 sleeping,   0 stopped,   0 zombie
    Cpu(s):  0.9%us,  3.7%sy,  0.0%ni, 95.5%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
    Mem:  16330584k total,  2335148k used, 13995436k free,   241348k buffers
    Swap:  4194296k total,        0k used,  4194296k free,  1631880k cached
    
    PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    24402 SK      20   0 98.7m 1072  860 S 19.0  0.0   0:12.44 a.out
    
  2. Můžete použít ps (například ve skriptu shellu)

    ps --format pid,pcpu,cputime,etime,size,vsz,cmd -p `pidof a.out`
    

    Potřebuji nějaké prostředky pro záznam výkonu aplikace na počítači se systémem Linux

    Chcete-li to provést, musíte použít perf pokud je vaše jádro Linuxu vyšší než 2.6.32 nebo OProfile, pokud je starší. Oba programy od vás nevyžadují instrumentaci vašeho programu (jako Gprof vyžaduje). Chcete-li však správně získat graf volání v perf musíte sestavit svůj program pomocí -fno-omit-frame-pointer. Například:g++ -fno-omit-frame-pointer -O2 main.cpp .

Jako pro Linux perf :

  1. Záznam údajů o výkonu:

    perf record -p `pidof a.out`
    

    nebo pro záznam po dobu 10 sekund:

    perf record -p `pidof a.out` sleep 10
    

    nebo pro záznam pomocí grafu hovorů ()

    perf record -g -p `pidof a.out`
    
  2. Pro analýzu zaznamenaných dat

    perf report --stdio
    perf report --stdio --sort=dso -g none
    perf report --stdio -g none
    perf report --stdio -g
    

    Na RHEL 6.3 je povoleno číst /boot/System.map-2.6.32-279.el6.x86_64, takže obvykle přidávám --kallsyms=/boot/System.map-2.6.32-279.el6.x86_64, když vytvoření zprávy o výkonu:

    perf report --stdio -g --kallsyms=/boot/System.map-2.6.32-279.el6.x86_64
    
    Zde jsem napsal nějaké další informace o používání Linuxu `perf`:

    Za prvé - toto je tutoriál o profilování Linuxu pomocí perf

    Můžete použít perf pokud je vaše jádro Linuxu vyšší než 2.6.32 nebo OProfile, pokud je starší. Oba programy od vás nevyžadují instrumentaci vašeho programu (jako Gprof vyžaduje). Abychom však správně získali graf hovorů v perf potřebujete sestavit svůj program s -fno-omit-frame-pointer . Například:g++ -fno-omit-frame-pointer -O2 main.cpp .

    Můžete vidět "živou" analýzu vaší aplikace pomocí perf top :

     sudo perf top -p `pidof a.out` -K
    

Nebo můžete zaznamenat údaje o výkonu běžící aplikace a poté je analyzovat:

  1. Záznam údajů o výkonu:

    perf record -p `pidof a.out`
    

    nebo pro záznam po dobu 10 sekund:

    perf record -p `pidof a.out` sleep 10
    

    nebo pro záznam pomocí grafu hovorů ()

    perf record -g -p `pidof a.out`
    
  2. Pro analýzu zaznamenaných dat

perf report --stdio
perf report --stdio --sort=dso -g none
perf report --stdio -g none
perf report --stdio -g

Nebo můžete zaznamenat údaje o výkonu aplikace a poté je analyzovat pouhým spuštěním aplikace tímto způsobem a čekáním na její ukončení:

perf record ./a.out

Toto je příklad profilování testovacího programu.

Testovací program je v souboru main.cpp (main.cpp je na konci odpovědi):

Zkompiluji to takto:

g++ -m64 -fno-omit-frame-pointer -g main.cpp -L.  -ltcmalloc_minimal -o my_test

Používám libmalloc_minimial.so, protože je kompilován s -fno-omit-frame-pointer, zatímco libc malloc se zdá být kompilován bez této možnosti. Poté spustím svůj testovací program:

./my_test 100000000

Poté zaznamenám údaje o výkonu běžícího procesu:

perf record -g  -p `pidof my_test` -o ./my_test.perf.data sleep 30

Poté analyzuji zatížení na modul:

perf report --stdio -g none --sort comm,dso -i ./my_test.perf.data

# Overhead  Command                 Shared Object
# ........  .......  ............................
#
    70.06%  my_test  my_test
    28.33%  my_test  libtcmalloc_minimal.so.0.1.0
     1.61%  my_test  [kernel.kallsyms]

Poté se analyzuje zatížení na funkci:

perf report --stdio -g none -i ./my_test.perf.data | c++filt

# Overhead  Command                 Shared Object                       Symbol
# ........  .......  ............................  ...........................
#
    29.30%  my_test  my_test                       [.] f2(long)
    29.14%  my_test  my_test                       [.] f1(long)
    15.17%  my_test  libtcmalloc_minimal.so.0.1.0  [.] operator new(unsigned long)
    13.16%  my_test  libtcmalloc_minimal.so.0.1.0  [.] operator delete(void*)
     9.44%  my_test  my_test                       [.] process_request(long)
     1.01%  my_test  my_test                       [.] operator delete(void*)@plt
     0.97%  my_test  my_test                       [.] operator new(unsigned long)@plt
     0.20%  my_test  my_test                       [.] main
     0.19%  my_test  [kernel.kallsyms]             [k] apic_timer_interrupt
     0.16%  my_test  [kernel.kallsyms]             [k] _spin_lock
     0.13%  my_test  [kernel.kallsyms]             [k] native_write_msr_safe

     and so on ...

Poté jsou analyzovány řetězce volání:

perf report --stdio -g graph -i ./my_test.perf.data | c++filt

# Overhead  Command                 Shared Object                       Symbol
# ........  .......  ............................  ...........................
#
    29.30%  my_test  my_test                       [.] f2(long)
            |
            --- f2(long)
               |
                --29.01%-- process_request(long)
                          main
                          __libc_start_main

    29.14%  my_test  my_test                       [.] f1(long)
            |
            --- f1(long)
               |
               |--15.05%-- process_request(long)
               |          main
               |          __libc_start_main
               |
                --13.79%-- f2(long)
                          process_request(long)
                          main
                          __libc_start_main

    15.17%  my_test  libtcmalloc_minimal.so.0.1.0  [.] operator new(unsigned long)
            |
            --- operator new(unsigned long)
               |
               |--11.44%-- f1(long)
               |          |
               |          |--5.75%-- process_request(long)
               |          |          main
               |          |          __libc_start_main
               |          |
               |           --5.69%-- f2(long)
               |                     process_request(long)
               |                     main
               |                     __libc_start_main
               |
                --3.01%-- process_request(long)
                          main
                          __libc_start_main

    13.16%  my_test  libtcmalloc_minimal.so.0.1.0  [.] operator delete(void*)
            |
            --- operator delete(void*)
               |
               |--9.13%-- f1(long)
               |          |
               |          |--4.63%-- f2(long)
               |          |          process_request(long)
               |          |          main
               |          |          __libc_start_main
               |          |
               |           --4.51%-- process_request(long)
               |                     main
               |                     __libc_start_main
               |
               |--3.05%-- process_request(long)
               |          main
               |          __libc_start_main
               |
                --0.80%-- f2(long)
                          process_request(long)
                          main
                          __libc_start_main

     9.44%  my_test  my_test                       [.] process_request(long)
            |
            --- process_request(long)
               |
                --9.39%-- main
                          __libc_start_main

     1.01%  my_test  my_test                       [.] operator delete(void*)@plt
            |
            --- operator delete(void*)@plt

     0.97%  my_test  my_test                       [.] operator new(unsigned long)@plt
            |
            --- operator new(unsigned long)@plt

     0.20%  my_test  my_test                       [.] main
     0.19%  my_test  [kernel.kallsyms]             [k] apic_timer_interrupt
     0.16%  my_test  [kernel.kallsyms]             [k] _spin_lock
     and so on ...

V tuto chvíli tedy víte, kde váš program tráví čas.

A toto je main.cpp soubor pro test:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

time_t f1(time_t time_value)
{
  for (int j = 0; j < 10; ++j) {
    ++time_value;
    if (j%5 == 0) {
      double *p = new double;
      delete p;
    }
  }
  return time_value;
}

time_t f2(time_t time_value)
{
  for (int j = 0; j < 40; ++j) {
    ++time_value;
  }
  time_value = f1(time_value);
  return time_value;
}

time_t process_request(time_t time_value)
{
  for (int j = 0; j < 10; ++j) {
    int *p = new int;
    delete p;
    for (int m = 0; m < 10; ++m) {
      ++time_value;
    }
  }
  for (int i = 0; i < 10; ++i) {
    time_value = f1(time_value);
    time_value = f2(time_value);
  }
  return time_value;
}

int main(int argc, char* argv2[])
{
  int number_loops = argc > 1 ? atoi(argv2[1]) : 1;
  time_t time_value = time(0);
  printf("number loops %d\n", number_loops);
  printf("time_value: %d\n", time_value);

  for (int i = 0; i < number_loops; ++i) {
    time_value = process_request(time_value);
  }
  printf("time_value: %ld\n", time_value);
  return 0;
}

Cituji samotného Linuse Torvaldse:

Nepoužívejte gprof. Jste moc lepší je použít nový linuxový nástroj 'perf'.

A později ...

Mohu téměř zaručit, že jakmile jej začnete používat, už nikdy nebudete používat gprof nebo oprofile.

Viz Re:[PATCH] grep:neprovádějte externí grep u položek skip-worktree (2010-01-04)


Linux
  1. Omezení přístupu k systémovému volání pro aplikaci Linux

  2. Spusťte aplikaci Java jako službu v systému Linux

  3. Získání seznamu spouštěcích aplikací v linuxu

  1. Jak nainstalovat aplikaci Spotify na Linux

  2. Linux – příkaz k měření chyb Tlb na Linuxu?

  3. Linux – jakou aplikaci použít pro kalendář?

  1. Linux – nepodařilo se nainstalovat Perf na Slackware 13.1?

  2. Jak podepsat aplikaci Mac OS X v Linuxu?

  3. Vyhněte se rušení linuxové aplikace kvůli nedostatku paměti