Dinamik analiz yöntemleri
Burada birkaç dinamik analiz yöntemini anlatıyorum.
Dinamik yöntemler aslında çağrı grafiğini belirlemek için programı çalıştırır.
Dinamik yöntemlerin tersi, programı çalıştırmadan tek başına kaynaktan belirlemeye çalışan statik yöntemlerdir.
Dinamik yöntemlerin avantajları:
- işlev işaretlerini ve sanal C ++ çağrılarını yakalar. Bunlar önemsiz olmayan herhangi bir yazılımda çok sayıda bulunur.
Dinamik yöntemlerin dezavantajları:
- programı çalıştırmanız gerekir, bu yavaş olabilir veya sahip olmadığınız bir kurulum gerektirebilir, örneğin çapraz derleme
- yalnızca gerçekten çağrılan işlevler gösterilecektir. Örneğin, komut satırı argümanlarına bağlı olarak bazı işlevler çağrılabilir veya çağrılmayabilir.
KcacheGrind
https://kcachegrind.github.io/html/Home.html
Test programı:
int f2(int i) { return i + 2; }
int f1(int i) { return f2(2) + i + 1; }
int f0(int i) { return f1(1) + f2(2); }
int pointed(int i) { return i; }
int not_called(int i) { return 0; }
int main(int argc, char **argv) {
int (*f)(int);
f0(1);
f1(1);
f = pointed;
if (argc == 1)
f(1);
if (argc == 2)
not_called(1);
return 0;
}
Kullanım:
sudo apt-get install -y kcachegrind valgrind
# Compile the program as usual, no special flags.
gcc -ggdb3 -O0 -o main -std=c99 main.c
# Generate a callgrind.out.<PID> file.
valgrind --tool=callgrind ./main
# Open a GUI tool to visualize callgrind data.
kcachegrind callgrind.out.1234
Artık birçok ilginç performans verisi içeren harika bir GUI programının içinde kaldınız.
Sağ alttaki "Arama grafiği" sekmesini seçin. Bu, işlevleri tıklattığınızda diğer pencerelerdeki performans ölçümleriyle ilişkilendirilen etkileşimli bir arama grafiğini gösterir.
Grafiği dışa aktarmak için sağ tıklayın ve "Grafiği Dışa Aktar" ı seçin. Dışa aktarılan PNG şu şekilde görünür:
Bundan şunu görebiliriz:
- kök düğüm,
_start
gerçek ELF giriş noktasıdır ve glibc başlatma şablonunu içerir
f0
, f1
Ve f2
birbirinden beklendiği gibi denir
pointed
bir işlev göstericisi ile adlandırmamıza rağmen de gösterilmektedir. Bir komut satırı argümanı iletmiş olsaydık çağrılmamış olabilirdi.
not_called
Ekstra bir komut satırı argümanı iletmediğimiz için çalıştırmada çağrılmadığı için gösterilmez.
Güzel olan yanı valgrind
, herhangi bir özel derleme seçeneği gerektirmemesidir.
Bu nedenle, kaynak kodunuz olmasa bile, yalnızca çalıştırılabilir olanı kullanabilirsiniz.
valgrind
kodunuzu hafif bir "sanal makine" üzerinden çalıştırarak bunu başarır. Bu aynı zamanda yürütmeyi yerel yürütmeye kıyasla oldukça yavaş hale getirir.
Grafikte görülebileceği gibi, her bir işlev çağrısı hakkında zamanlama bilgisi de elde edilir ve bu, yalnızca çağrı grafiklerini görmek için değil, muhtemelen bu kurulumun orijinal kullanım durumu olan programın profilini çıkarmak için kullanılabilir: Nasıl profil oluşturabilirim Linux üzerinde çalışan C ++ kodu?
Ubuntu 18.04'te test edildi.
gcc -finstrument-functions
+ etrace
https://github.com/elcritch/etrace
-finstrument-functions
geri aramalar ekler , etrace ELF dosyasını ayrıştırır ve tüm geri aramaları uygular.
Ancak maalesef çalışmasını sağlayamadım : Neden "-finstrument-functions" bende çalışmıyor?
Talep edilen çıktı şu formattadır:
\-- main
| \-- Crumble_make_apple_crumble
| | \-- Crumble_buy_stuff
| | | \-- Crumble_buy
| | | \-- Crumble_buy
| | | \-- Crumble_buy
| | | \-- Crumble_buy
| | | \-- Crumble_buy
| | \-- Crumble_prepare_apples
| | | \-- Crumble_skin_and_dice
| | \-- Crumble_mix
| | \-- Crumble_finalize
| | | \-- Crumble_put
| | | \-- Crumble_put
| | \-- Crumble_cook
| | | \-- Crumble_put
| | | \-- Crumble_bake
Muhtemelen, belirli donanım izleme desteğinin yanı sıra en verimli yöntemdir, ancak kodu yeniden derlemenizin dezavantajı vardır.