गतिशील विश्लेषण के तरीके
यहाँ मैं कुछ गतिशील विश्लेषण विधियों का वर्णन करता हूँ।
डायनामिक तरीके वास्तव में कॉल ग्राफ को निर्धारित करने के लिए प्रोग्राम चलाते हैं।
गतिशील तरीकों के विपरीत स्थिर विधियां हैं, जो कार्यक्रम को चलाने के बिना अकेले स्रोत से इसे निर्धारित करने का प्रयास करते हैं।
गतिशील विधियों के लाभ:
- फंक्शन पॉइंटर्स और वर्चुअल C ++ कॉल को पकड़ता है। ये किसी भी गैर-तुच्छ सॉफ़्टवेयर में बड़ी संख्या में मौजूद हैं।
गतिशील तरीकों का नुकसान:
- आपको प्रोग्राम चलाना होगा, जो धीमा हो सकता है, या एक सेटअप की आवश्यकता होती है जो आपके पास नहीं है, जैसे कि क्रॉस-संकलन
- केवल ऐसे कार्य जो वास्तव में कहे गए थे, दिखाए जाएंगे। उदाहरण के लिए, कमांड लाइन के तर्कों के आधार पर कुछ कार्यों को बुलाया जा सकता है या नहीं।
KcacheGrind
https://kcachegrind.github.io/html/Home.html
परीक्षण कार्यक्रम:
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;
}
उपयोग:
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
अब आप एक भयानक GUI प्रोग्राम के अंदर रह गए हैं जिसमें बहुत सारे दिलचस्प प्रदर्शन डेटा हैं।
नीचे दाईं ओर, "कॉल ग्राफ़" टैब चुनें। यह एक इंटरेक्टिव कॉल ग्राफ़ दिखाता है जो अन्य विंडो में मेट्रिक्स के प्रदर्शन से संबंधित है, जैसा कि आप फ़ंक्शंस पर क्लिक करते हैं।
ग्राफ़ को निर्यात करने के लिए, इसे राइट क्लिक करें और "एक्सपोर्ट ग्राफ़" चुनें। निर्यात किया गया पीएनजी इस तरह दिखता है:
उस से हम देख सकते हैं कि:
- रूट नोड है
_start
, जो कि वास्तविक ईएलएफ प्रवेश बिंदु है, और इसमें ग्लिबैक इनिशियलाइज़ेशन बॉयलरप्लेट है
f0
, f1
और f2
एक दूसरे से अपेक्षित के रूप में कहा जाता है
pointed
यह भी दिखाया गया है, भले ही हमने इसे फ़ंक्शन पॉइंटर के साथ बुलाया हो। यदि हम कमांड लाइन तर्क पारित कर चुके होते तो इसे नहीं बुलाया जाता।
not_called
यह नहीं दिखाया गया है क्योंकि इसे रन में नहीं बुलाया गया, क्योंकि हमने एक अतिरिक्त कमांड लाइन तर्क पारित नहीं किया था।
इसके बारे valgrind
में अच्छी बात यह है कि इसके लिए किसी विशेष संकलन विकल्प की आवश्यकता नहीं है।
इसलिए, आप इसका उपयोग कर सकते हैं भले ही आपके पास स्रोत कोड न हो, केवल निष्पादन योग्य।
valgrind
एक हल्के "आभासी मशीन" के माध्यम से अपना कोड चलाकर ऐसा करने का प्रबंधन करता है। यह देशी निष्पादन की तुलना में निष्पादन को बहुत धीमा बनाता है।
जैसा कि ग्राफ पर देखा जा सकता है, प्रत्येक फ़ंक्शन कॉल के बारे में समय की जानकारी भी प्राप्त की जाती है, और इसका उपयोग प्रोग्राम को प्रोफाइल करने के लिए किया जा सकता है, जो कि इस सेटअप के मूल उपयोग के मामले की संभावना है, न कि केवल कॉल ग्राफ़ को देखने के लिए: मैं कैसे प्रोफ़ाइल कर सकता हूं लिनक्स पर चलने वाला C ++ कोड?
उबंटू 18.04 पर परीक्षण किया गया।
gcc -finstrument-functions
+ एट्रेस
https://github.com/elcritch/etrace
-finstrument-functions
कॉलबैक जोड़ता है , एट्रेस ईएलएफ फ़ाइल को पार्स करता है और सभी कॉलबैक को लागू करता है।
मैं इसे दुर्भाग्य से काम नहीं कर सका: मेरे लिए `-finstrument-functions` काम क्यों नहीं करता है?
दावा किया गया आउटपुट प्रारूप का है:
\-- 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
विशिष्ट हार्डवेयर ट्रेसिंग समर्थन के अलावा सबसे कुशल विधि, लेकिन नकारात्मक पक्ष यह है कि आपको कोड को फिर से भरना होगा।