Analiza pokrycia kodu i profilowanie aplikacji

Wykorzystanie kodu - gcov

Jest to program, który pozwala analizować pokrycie kodu. Jest to szczególnie istotne podczas testowania aplikacji a także analizy wydajności. Narzędzie pozwala stwierdzić, czy wszystkie warianty wykonania kodu zostały uruchomione podczas testów a także znajduje linie, które wykonują się szczególnie często i mogą wymagać optymalizacji.

Aby korzystać z gcov, należy skompilować analizowany program z opcjami: -fprofile-arcs i -ftest-coverage. W plikach wykonywalnych umieszczane są dodatkowe informacje. Dodatkowo tworzone są pliki wymagane przez program. Uruchomienie skompilowanego programu powoduje zapisanie informacji diagnostycznych. Dla każdego pliku źródłowego, skompilowanego z opcją -fprofile-arcs, otrzymujemy plik .gcda.

Uruchomienie gcov <nazwa pliku źródłowego>, tworzy opis kodu źródłowego, zawierający informację o ilości wywołań każdej linii.

Przykładowy program realizujący obliczanie pierwiastka kwadratowego z liczby całkowitej:

sqrt.c
#include <stdio.h>
 
short mysqrt(long num) {
    long op = num;
    long res = 0;
    long one = 1L << 30;
 
    /* "one" ustawiany na największą potęgę 4 nie większą niż argument */
    while (one > op)
        one >>= 2;
 
    while (one != 0) {
        if (op >= res + one) {
            op -= res + one;
            res = (res >> 1) + one;
        }
        else
          res >>= 1;
        one >>= 2;
    }
    return res;
}
 
int main() {
  printf("%ld\n",mysqrt(65536));
  return 0;
}

I jego analiza:

$ gcc -fprofile-arcs -ftest-coverage -o sqrt sqrt.c
$ ./sqrt
$ gcov sqrt.c 
File 'sqrt.c'
Lines executed:100.00% of 16
sqrt.c:creating 'sqrt.c.gcov'

Nowo-utworzony plik *.gcov, zawiera wyjście programu - analizę pokrycia:

        -:    0:Source:sqrt.c
        -:    0:Graph:sqrt.gcno
        -:    0:Data:sqrt.gcda
        -:    0:Runs:1
        -:    0:Programs:1
        -:    1:#include <stdio.h>
        -:    2:
        1:    3:short mysqrt(long num) {
        1:    4:    long op = num;
        1:    5:    long res = 0;
        1:    6:    long one = 1L << 30;
        -:    7:
        -:    8:    // "one" ustawiany na największą potęgę 4 nie większą niż argument
        9:    9:    while (one > op)
        7:   10:        one >>= 2;
        -:   11:
       11:   12:    while (one != 0) {
        9:   13:        if (op >= res + one) {
        1:   14:            op -= res + one;
        1:   15:            res = (res >> 1) + one;
        -:   16:        }
        -:   17:        else
        8:   18:          res >>= 1;
        9:   19:        one >>= 2;
        -:   20:    }
        1:   21:    return res;
        -:   22:}
        -:   23:
        1:   24:int main() {
        1:   25:  printf("%ld\n",mysqrt(65536));
        1:   26:  return 0;
        -:   27:}

Dla każdej linii kodu, wypisana została ilość jej wykonań.

Profilowanie wykonania kodu - gprof

Użycie programu polega na skompilowaniu kodu z opcją -pg - musi zostać dodana zarówno przy kompilacji, jak i podczas konsolidacji:

gcc -o sqrt -pg sqrt.c
./sqrt

Po uruchomieniu skompilowanego w ten sposób programu, tworzony jest plik:

gmon.out

Zawiera on dane pozyskane w trakcie działania programu, które mogą być wyświetlane (i odpowiednio sformatowane) przy pomocy narzędzia gprof.

Prosta analiza

Pokazuje ile czasu program spędza wywołując którą funkcję:

$ gprof -p sqrt
Flat profile:

Each sample counts as 0.01 seconds.
 no time accumulated

  %   cumulative   self              self     total           
 time   seconds   seconds    calls  Ts/call  Ts/call  name    
  0.00      0.00     0.00        1     0.00     0.00  mysqrt

Drzewo wywołań

$ gprof -q sqrt
		     Call graph (explanation follows)


granularity: each sample hit covers 2 byte(s) no time propagated

index % time    self  children    called     name
                0.00    0.00       1/1           main [6]
[1]      0.0    0.00    0.00       1         mysqrt [1]
-----------------------------------------------

Kod źródłowy wraz z komentarzem dotyczącym profilowania

Ta opcja wymaga skompilowania programu z dodatkowymi symbolami debuggera (-g). Uruchomienie następuje po wydaniu polecenia:

$ gprof -A sqrt

Funkcje zostają oznakowane ilością uruchomień:

           1 -> short mysqrt(long num) {
...
       ##### -> int main() {

Na końcu wyświetlane jest podsumowanie:

Top 10 Lines:

     Line      Count

        3          1

Execution Summary:

        2   Executable lines in this file
        2   Lines executed
   100.00   Percent of the file executed

        1   Total number of line executions
     0.50   Average executions per line

Inne

Pozostałe opcje formatowania danych profilowania, opisane są w podręczniku systemowym: \texttt{man gprof}.

ostatnio zmienione: 2011/07/17 21:12