मैं लिनक्स पर चलने वाले C ++ कोड को कैसे प्रोफाइल कर सकता हूं?


1815

मेरे पास C ++ एप्लिकेशन है, जो लिनक्स पर चल रहा है, जिसे मैं अनुकूलित करने की प्रक्रिया में हूं। मैं यह कैसे इंगित कर सकता हूं कि मेरे कोड के कौन से क्षेत्र धीरे-धीरे चल रहे हैं?


27
यदि आप अपने विकास स्टैक के बारे में अधिक डेटा प्रदान करेंगे तो आपको बेहतर उत्तर मिल सकते हैं। इंटेल और सन से प्रोफाइल हैं लेकिन आपको उनके कंपाइलरों का उपयोग करना होगा। क्या वह विकल्प है?
नाजगॉब

2
यह निम्नलिखित लिंक पर पहले से ही उत्तर दिया गया है: stackoverflow.com/questions/2497211/…
कपिल गुप्ता

4
अधिकांश उत्तर codeप्रोफाइलर हैं। हालांकि, प्राथमिकता उलटा, कैश एलियासिंग, संसाधन विवाद, आदि सभी अनुकूलन और प्रदर्शन के कारक हो सकते हैं। मुझे लगता है कि लोग मेरे धीमे कोड में जानकारी पढ़ते हैं । एफएक्यू इस धागे को संदर्भित कर रहे हैं।
आर्टलेस शोर


3
मैंने pstack का उपयोग बेतरतीब ढंग से करने के लिए किया, अधिकांश समय सबसे विशिष्ट स्टैक का प्रिंट आउट करेगा जहाँ प्रोग्राम अधिकांश समय होता है, इसलिए टोंटी की ओर इशारा करता है।
जोस मैनुअल गोमेज़ अल्वारेज़

जवाबों:


1404

यदि आपका लक्ष्य एक प्रोफाइलर का उपयोग करना है, तो सुझाए गए किसी एक का उपयोग करें।

हालाँकि, अगर आप जल्दी में हैं और आप डिबगर के तहत अपने प्रोग्राम को मैन्युअल रूप से बाधित कर सकते हैं, जबकि यह विषयगत रूप से धीमा है, तो प्रदर्शन समस्याओं को खोजने का एक सरल तरीका है।

बस इसे कई बार रोकें, और हर बार कॉल स्टैक को देखें। यदि कुछ कोड है जो समय का कुछ प्रतिशत, 20% या 50% या जो भी बर्बाद कर रहा है, वह संभावना है कि आप इसे प्रत्येक नमूने पर अधिनियम में पकड़ लेंगे। तो, यह मोटे तौर पर नमूनों का प्रतिशत है जिस पर आप इसे देखेंगे। कोई शिक्षित अनुमान नहीं है। यदि आपके पास एक अनुमान है कि समस्या क्या है, तो यह साबित होगा या इसे अस्वीकृत कर देगा।

आपको विभिन्न आकारों की कई प्रदर्शन समस्याएं हो सकती हैं। यदि आप उनमें से किसी एक को साफ करते हैं, तो शेष लोग एक बड़ा प्रतिशत लेंगे, और बाद में पास होने पर हाजिर होना आसान होगा। यह आवर्धन प्रभाव , जब कई समस्याओं पर समझौता किया जाता है, तो वास्तव में बड़े पैमाने पर स्पीडअप कारक हो सकते हैं।

कैविएट : प्रोग्रामर इस तकनीक पर तब तक संदेह करते हैं जब तक कि वे खुद इसका इस्तेमाल नहीं करते। वे कहेंगे कि प्रोफाइलर्स आपको इसकी जानकारी देते हैं, लेकिन यह केवल तभी सच है जब वे पूरे कॉल स्टैक का नमूना लेते हैं, और फिर आपको नमूनों के एक यादृच्छिक सेट की जांच करते हैं। (सारांश वे हैं जहां अंतर्दृष्टि खो गई है।) कॉल ग्राफ़ आपको समान जानकारी नहीं देते हैं, क्योंकि

  1. वे अनुदेश स्तर पर संक्षेप में प्रस्तुत नहीं करते हैं, और
  2. वे पुनरावृत्ति की उपस्थिति में भ्रामक सारांश देते हैं।

वे यह भी कहेंगे कि यह केवल खिलौना कार्यक्रमों पर काम करता है, जब वास्तव में यह किसी भी कार्यक्रम पर काम करता है, और यह बड़े कार्यक्रमों पर बेहतर काम करता है, क्योंकि वे खोजने के लिए अधिक समस्याएं रखते हैं। वे कहते हैं कि यह कभी-कभी उन चीजों को ढूंढता है जो समस्याएं नहीं हैं, लेकिन यह केवल सच है अगर आप एक बार कुछ देखते हैं । यदि आप एक से अधिक नमूने पर समस्या देखते हैं, तो यह वास्तविक है।

PS यह बहु-थ्रेड प्रोग्रामों पर भी किया जा सकता है अगर वहाँ एक बिंदु पर थ्रेड पूल के कॉल-स्टैक नमूने एकत्र करने का एक तरीका है, जैसा कि जावा में है।

पीपीएस एक मोटे तौर पर सामान्यता के रूप में, आपके सॉफ्टवेयर में आपके द्वारा अमूर्तता की जितनी अधिक परतें हैं, उतनी ही अधिक संभावना है कि आप पाएंगे कि प्रदर्शन समस्याओं का कारण है (और स्पीडअप प्राप्त करने का अवसर)।

जोड़ा गया : यह स्पष्ट नहीं हो सकता है, लेकिन स्टैक सैंपलिंग तकनीक पुनरावृत्ति की उपस्थिति में समान रूप से अच्छी तरह से काम करती है। कारण यह है कि एक निर्देश को हटाकर जो समय बचाया जाएगा, उसमें नमूने के अंश द्वारा अनुमानित किया गया है, भले ही किसी नमूने के भीतर कितनी भी बार हो।

एक और आपत्ति मैं अक्सर सुनता हूं: " यह कहीं न कहीं यादृच्छिक रूप से बंद हो जाएगा, और यह वास्तविक समस्या को याद करेगा "। यह वास्तविक समस्या क्या है की एक पूर्व अवधारणा होने से आता है। प्रदर्शन की समस्याओं का एक प्रमुख गुण यह है कि वे अपेक्षाओं को धता बताते हैं। नमूना आपको बताता है कि कुछ समस्या है, और आपकी पहली प्रतिक्रिया अविश्वास है। यह स्वाभाविक है, लेकिन आप यह सुनिश्चित कर सकते हैं कि अगर यह एक समस्या है तो यह वास्तविक है, और इसके विपरीत।

जोड़ा गया : मुझे कैसे काम करता है इसका बायेसियन विवरण दें। मान लीजिए कि कुछ निर्देश है I(कॉल या अन्यथा) जो कॉल स्टैक fपर है समय के कुछ अंश (और इस तरह उस लागत का)। सादगी के लिए, मान लें कि हम नहीं जानते कि क्या fहै, लेकिन मान लें कि यह 0.1, 0.2, 0.3, ... 0.9, 1.0 और इन संभावनाओं में से प्रत्येक की पूर्व संभावना 0.1 है, इसलिए इन सभी लागतों की समान रूप से संभावना है संभवतः।

तब मान लें कि हम केवल 2 स्टैक नमूने लेते हैं, और हम Iदोनों नमूनों पर निर्देश देखते हैं, निर्दिष्ट अवलोकन o=2/2। यह हमें इस के अनुसार की आवृत्ति fका नया अनुमान देता है I:

Prior                                    
P(f=x) x  P(o=2/2|f=x) P(o=2/2&&f=x)  P(o=2/2&&f >= x)  P(f >= x | o=2/2)

0.1    1     1             0.1          0.1            0.25974026
0.1    0.9   0.81          0.081        0.181          0.47012987
0.1    0.8   0.64          0.064        0.245          0.636363636
0.1    0.7   0.49          0.049        0.294          0.763636364
0.1    0.6   0.36          0.036        0.33           0.857142857
0.1    0.5   0.25          0.025        0.355          0.922077922
0.1    0.4   0.16          0.016        0.371          0.963636364
0.1    0.3   0.09          0.009        0.38           0.987012987
0.1    0.2   0.04          0.004        0.384          0.997402597
0.1    0.1   0.01          0.001        0.385          1

                  P(o=2/2) 0.385                

अंतिम कॉलम कहता है कि, उदाहरण के लिए, संभावना है कि f> = 0.5 92% है, 60% की पूर्व धारणा से।

माना कि पूर्व धारणाएं अलग हैं। मान लीजिए हम ग्रहण करते हैं P(f=0.1)।991 (लगभग निश्चित), और अन्य सभी संभावनाएं लगभग असंभव (0.001) हैं। दूसरे शब्दों में, हमारी पूर्व निश्चितता Iसस्ती है। फिर हमें मिलता है:

Prior                                    
P(f=x) x  P(o=2/2|f=x) P(o=2/2&& f=x)  P(o=2/2&&f >= x)  P(f >= x | o=2/2)

0.001  1    1              0.001        0.001          0.072727273
0.001  0.9  0.81           0.00081      0.00181        0.131636364
0.001  0.8  0.64           0.00064      0.00245        0.178181818
0.001  0.7  0.49           0.00049      0.00294        0.213818182
0.001  0.6  0.36           0.00036      0.0033         0.24
0.001  0.5  0.25           0.00025      0.00355        0.258181818
0.001  0.4  0.16           0.00016      0.00371        0.269818182
0.001  0.3  0.09           0.00009      0.0038         0.276363636
0.001  0.2  0.04           0.00004      0.00384        0.279272727
0.991  0.1  0.01           0.00991      0.01375        1

                  P(o=2/2) 0.01375                

अब यह P(f >= 0.5)26% है, जो 0.6% की पूर्व धारणा से ऊपर है। तो Bayes हमें संभावित लागत के हमारे अनुमान को अपडेट करने की अनुमति देता है I। यदि डेटा की मात्रा छोटी है, तो यह हमें सटीक रूप से नहीं बताता है कि लागत क्या है, केवल यह कि यह फिक्सिंग के लायक है।

फिर भी इसे देखने का एक और तरीका नियम का उत्तराधिकार कहा जाता है । यदि आप एक सिक्का 2 बार फ्लिप करते हैं, और यह दोनों बार सिर आता है, तो इससे आपको सिक्के के संभावित भार के बारे में क्या पता चलता है? जवाब देने का सम्मानित तरीका यह है कि यह औसत मूल्य के साथ एक बीटा वितरण है (number of hits + 1) / (number of tries + 2) = (2+1)/(2+2) = 75%

(कुंजी यह है कि हम Iएक से अधिक बार देखते हैं । यदि हम इसे केवल एक बार देखते हैं, तो यह हमें इसके अलावा नहीं बताता है f> 0.)

इसलिए, यहां तक ​​कि बहुत कम संख्या में नमूने हमें निर्देशों की लागत के बारे में बहुत कुछ बता सकते हैं जो इसे देखता है। (और यह औसत, उनकी लागत के लिए आनुपातिक पर एक आवृत्ति के साथ उन्हें देख सकें। यदि nनमूने लिया जाता है, और fलागत है, तो Iपर दिखाई देगा nf+/-sqrt(nf(1-f))नमूने हैं। उदाहरण के लिए, n=10, f=0.3, वह यह है कि 3+/-1.4नमूने हैं।)


जोड़ा गया : मापने और यादृच्छिक स्टैक नमूने के बीच अंतर के लिए एक सहज ज्ञान युक्त अनुभव देने के लिए:
अब प्रोफाइलर हैं जो स्टैक का नमूना करते हैं, यहां तक ​​कि दीवार-घड़ी के समय पर भी, लेकिन जो सामने आता है वह माप (या गर्म पथ, या गर्म स्थान) है, जिसमें से एक "अड़चन" आसानी से छिपा सकती है)। वे आपको क्या नहीं दिखाते हैं (और वे आसानी से कर सकते हैं) स्वयं वास्तविक नमूने हैं। और अगर आपका लक्ष्य अड़चन को खोजने का है, तो आपको उनमें से जो संख्या देखने की जरूरत है, वह औसतन 2 उस समय के अंश से विभाजित होती है। इसलिए यदि यह 30% समय लेता है, तो 2 / .3 = 6.7 नमूने, औसतन, इसे दिखाएंगे, और 20 नमूनों को दिखाने का मौका 99.2% होगा।

यहाँ माप माप और स्टैक नमूनों की जाँच के बीच अंतर का एक ऑफ-द-कफ चित्रण है। अड़चन एक बड़ी बूँद की तरह हो सकती है, या कई छोटे लोग, इससे कोई फर्क नहीं पड़ता।

यहां छवि विवरण दर्ज करें

मापन क्षैतिज है; यह आपको बताता है कि विशिष्ट दिनचर्या का कौन सा समय लगता है। सैंपलिंग वर्टिकल है। यदि उस समय पूरा कार्यक्रम क्या कर रहा है, इससे बचने का कोई तरीका है, और यदि आप इसे दूसरे नमूने पर देखते हैं , तो आपको अड़चन मिल सकती है। बस यही फर्क पड़ता है - समय के पूरे कारण को देखते हुए, न सिर्फ कितना।


292
यह मूल रूप से एक गरीब आदमी का नमूना प्रोफाइलर है, जो बहुत अच्छा है, लेकिन आप बहुत छोटे नमूना आकार के जोखिम को चलाते हैं जो संभवतः आपको पूरी तरह से परिणाम देगा।
22:56

100
@ क्रैश: मैं "गरीब आदमी" भाग पर बहस नहीं करूंगा :-) यह सच है कि सांख्यिकीय माप सटीकता के लिए कई नमूनों की आवश्यकता होती है, लेकिन दो परस्पर विरोधी लक्ष्य हैं - माप और समस्या स्थान। मैं उत्तरार्द्ध पर ध्यान केंद्रित कर रहा हूं, जिसके लिए आपको स्थान की सटीकता की आवश्यकता है, माप की सटीकता की नहीं। इसलिए, उदाहरण के लिए, मध्य-स्टैक, एकल फ़ंक्शन कॉल ए () हो सकता है; वह 50% समय के लिए खाता है, लेकिन यह एक और बड़े समारोह बी में हो सकता है, साथ ही ए () के लिए कई अन्य कॉल भी महंगा नहीं है। फ़ंक्शन समय का सटीक सारांश एक सुराग हो सकता है, लेकिन हर दूसरे स्टैक नमूना समस्या को इंगित करेगा।
माइक डनलैवी

41
... दुनिया को लगता है कि एक कॉल-ग्राफ, कॉल काउंट और / या औसत समय के साथ एनोटेट काफी अच्छा है। यह नहीं। और दुखद बात यह है कि उन लोगों के लिए, जो कॉल स्टैक का नमूना लेते हैं, सबसे उपयोगी जानकारी उनके सामने सही है, लेकिन वे इसे "आंकड़े" के हितों में फेंक देते हैं।
माइक डनलैवी

30
मुझे आपकी तकनीक से असहमत होने का मतलब नहीं है। स्पष्ट रूप से मैं स्टैक-वॉकिंग सैंपलिंग प्रोफाइलर्स पर काफी भरोसा करता हूं। मैं सिर्फ यह इंगित कर रहा हूं कि कुछ उपकरण हैं जो इसे स्वचालित तरीके से करते हैं, जो महत्वपूर्ण है जब आप 25% से 15% तक एक फ़ंक्शन प्राप्त करने की बात कर रहे हैं और इसे 1.2% से नीचे खिसकाने की आवश्यकता है 0.6%।
क्रैशवर्ट्स

13
-1: नीट विचार, लेकिन अगर आपको मामूली प्रदर्शन उन्मुख वातावरण में काम करने के लिए भुगतान किया जा रहा है तो यह हर किसी के समय की बर्बादी है। एक वास्तविक प्रोफाइलर का उपयोग करें ताकि हमें आपके पीछे न आना पड़े और वास्तविक समस्याओं को ठीक करना पड़े।
सैम हरवेल

583

आप निम्न विकल्पों के साथ Valgrind का उपयोग कर सकते हैं

valgrind --tool=callgrind ./(Your binary)

यह एक फ़ाइल उत्पन्न करेगा जिसे कहा जाता है callgrind.out.x। आप kcachegrindइस फ़ाइल को पढ़ने के लिए उपकरण का उपयोग कर सकते हैं। यह आपको परिणामों के साथ चीजों का एक ग्राफिकल विश्लेषण देगा जैसे कि कौन सी लाइनों की लागत कितनी है।


51
वैलेरिंड महान है, लेकिन चेतावनी दी जाती है कि यह आपके कार्यक्रम को धीमा कर देगा
नीव

30
आउटपुट की कल्पना करने के लिए एक अद्भुत वैकल्पिक तरीके के लिए Gprof2Dot भी देखें./gprof2dot.py -f callgrind callgrind.out.x | dot -Tsvg -o output.svg
सेबस्टियन

2
@neves Yes Valgrind "gstreamer" और "opencv" अनुप्रयोगों के लिए वास्तविक समय में गति के मामले में बहुत उपयोगी नहीं है।
उत्साही

1
stackoverflow.com/questions/375913/… स्पीड इश्यू के लिए आंशिक विलेयॉन है।
तन्नु सैमुअल

3
@Sebastian: gprof2dot: अब यहाँ है github.com/jrfonseca/gprof2dot
जॉन Zwinck

347

मुझे लगता है कि आप जीसीसी का उपयोग कर रहे हैं। मानक समाधान ग्रेफाइट के साथ प्रोफाइल के लिए होगा ।

-pgप्रोफाइलिंग से पहले संकलन में जोड़ना सुनिश्चित करें :

cc -o myprog myprog.c utils.c -g -pg

मैंने अभी तक इसकी कोशिश नहीं की है, लेकिन मैंने google-perftools के बारे में अच्छी बातें सुनी हैं । यह निश्चित रूप से एक कोशिश के काबिल है।

संबंधित प्रश्न यहाँ

कुछ अन्य buzzwords अगर gprofआपके लिए काम नहीं करते हैं: Valgrind , Intel VTune , Sun DTrace


3
मैं मानता हूं कि लाभकारी वर्तमान मानक है। बस एक नोट, हालांकि, Valgrind का उपयोग मेमोरी लीक और आपके कार्यक्रमों के अन्य मेमोरी से संबंधित पहलुओं को प्रोफाइल करने के लिए किया जाता है, गति अनुकूलन के लिए नहीं।
छिपकली

68
बिल, वेजलिंड सूट में आप कॉलगर्ल और मासिफ़ पा सकते हैं। दोनों ही प्रोफाइल ऐप्स के लिए बहुत उपयोगी हैं
dario minonne 15

7
@ बिल-छिपकली: पर कुछ टिप्पणियां gprof : stackoverflow.com/questions/1777556/alternatives-to-gprof/...
माइक Dunlavey

6
gprof -pg केवल कॉलस्टैक प्रोफाइलिंग का एक अनुमान है। यह ट्रैक करने के लिए mcount कॉल्स सम्मिलित करता है कि कौन से फ़ंक्शंस कॉल कर रहे हैं जो अन्य फ़ंक्शन हैं। यह उह, समय के लिए मानक समय आधारित नमूने का उपयोग करता है। तब यह एक बार में एक समारोह फू () में फोन के नंबर की भविष्यवाणी में फू () के कॉल करने वालों के लिए नमूना लिया जाता है। इसलिए यह विभिन्न लागतों के कॉल के बीच अंतर नहीं करता है।
क्रेजी गेलव

1
क्लैंग / क्लैंग ++ के साथ, कोई व्यक्ति जीपीएफ के सीपीयू प्रोफाइलर का उपयोग करने पर विचार कर सकता है । कैविएट: खुद ऐसा नहीं किया है।
einpoklum

257

नए गुठली (उदाहरण के लिए नवीनतम उबंटू गुठली) नए 'perf' उपकरण ( apt-get install linux-tools) AKA perf_events के साथ आते हैं

ये क्लासिक सैंपलिंग प्रोफाइलर्स ( मैन-पेज ) के साथ-साथ कमाल की टाइमचर्ट के साथ आते हैं !

महत्वपूर्ण बात यह है कि ये उपकरण सिस्टम प्रोफाइलिंग हो सकते हैं, न कि केवल प्रक्रिया प्रोफाइलिंग - ये धागे, प्रक्रियाओं और कर्नेल के बीच की बातचीत को दिखा सकते हैं और आपको प्रक्रियाओं के बीच शेड्यूलिंग और I / O निर्भरता को समझने देते हैं।

वैकल्पिक शब्द


12
महान उपकरण! क्या मेरे लिए एक विशिष्ट "तितली" दृश्य प्राप्त करना है जो "मुख्य-> func1-> fun2" शैली से शुरू होता है? मुझे यह पता नहीं लग सकता है कि ... perf reportमुझे कॉल माता-पिता के साथ फ़ंक्शन नाम देने के लिए लगता है ... (इसलिए यह एक उल्टे तितली दृश्य की तरह है)
kizzx2

विल, थ्रेड गतिविधि के टाइमचार्ट को दिखा सकता है; CPU नंबर की जानकारी के साथ जोड़ा गया? मैं देखना चाहता हूं कि हर सीपीयू पर कब और कौन सा धागा चल रहा था।
osgx

2
@ kizzx2 - आप उपयोग कर सकते हैं gprof2dotऔर perf script। बहुत अच्छा उपकरण!
dashesy

2
4.13 जैसी नई गुठली में भी प्रोफाइलिंग के लिए ईजीपीएफ है। Brendangregg.com/blog/2015-05-15/ebpf-one-small-step.html और brendangregg.com/ebpf.html
एंड्रयू स्टर्न

एक और अच्छा परिचय पुरालेख मेंperf मौजूद है
।li

75

मैं अपने प्रोफाइलिंग सूट के लिए आधार के रूप में Valgrind और Callgrind का उपयोग करूंगा। यह जानना महत्वपूर्ण है कि Valgrind मूल रूप से एक वर्चुअल मशीन है:

(विकिपीडिया) वेलग्रिंड एक आभासी मशीन है जिसमें डायनेमिक कंपकंपी सहित जस्ट-इन-टाइम (जेआईटी) संकलन तकनीकों का उपयोग किया जाता है। मूल कार्यक्रम से कुछ भी कभी होस्ट प्रोसेसर पर सीधे नहीं चलता है। इसके बजाय, Valgrind पहले प्रोग्राम को एक अस्थायी, सरल रूप में अनुवाद करता है जिसे इंटरमीडिएट रिप्रेजेंटेशन (IR) कहा जाता है, जो एक प्रोसेसर-न्यूट्रल, SSA- आधारित फॉर्म है। रूपांतरण के बाद, एक उपकरण (नीचे देखें) आईआर पर जो भी रूपांतरण करना चाहते हैं, करने के लिए स्वतंत्र है, इससे पहले कि वालग्रिंड आईआर को वापस मशीन कोड में अनुवाद करता है और मेजबान प्रोसेसर को इसे चलाने देता है।

Callgrind उस पर एक प्रोफाइलर बिल्ड है। मुख्य लाभ यह है कि विश्वसनीय परिणाम प्राप्त करने के लिए आपको घंटों तक अपना प्रभाव नहीं चलाना पड़ता है। यहां तक ​​कि रॉक-सॉलिड, विश्वसनीय परिणाम प्राप्त करने के लिए एक सेकंड रन पर्याप्त है, क्योंकि कॉलग्रिंड एक गैर-जांच प्रोफाइल है।

Valgrind पर एक और उपकरण का निर्माण मासिफ है। मैं इसे हीप मेमोरी उपयोग को प्रोफाइल करने के लिए उपयोग करता हूं। यह बहुत अच्छा काम करता है। यह क्या करता है कि यह आपको मेमोरी उपयोग का स्नैपशॉट देता है - विस्तृत जानकारी WHAT कितने प्रतिशत मेमोरी रखती है, और डब्ल्यूएचओ ने इसे वहां रखा था। इस तरह की जानकारी आवेदन चलाने के समय के विभिन्न बिंदुओं पर उपलब्ध है।


70

चलाने valgrind --tool=callgrindका उत्तर कुछ विकल्पों के बिना काफी पूर्ण नहीं है। हम आमतौर पर Valgrind के तहत 10 मिनट के धीमे स्टार्टअप समय को प्रोफाइल नहीं करना चाहते हैं और जब यह कुछ काम कर रहा है तो हमारे प्रोग्राम को प्रोफाइल करना चाहता है।

तो मैं यही सलाह देता हूं। कार्यक्रम पहले चलाएं:

valgrind --tool=callgrind --dump-instr=yes -v --instr-atstart=no ./binary > tmp

अब जब यह काम करता है और हम प्रोफाइलिंग शुरू करना चाहते हैं तो हमें दूसरी विंडो में चलना चाहिए:

callgrind_control -i on

यह प्रोफाइलिंग चालू करता है। इसे बंद करने और पूरे कार्य को रोकने के लिए जिसका हम उपयोग कर सकते हैं:

callgrind_control -k

अब हमारे पास मौजूदा निर्देशिका में callgrind.out। * नाम की कुछ फाइलें हैं। प्रोफाइलिंग परिणामों का उपयोग देखने के लिए:

kcachegrind callgrind.out.*

मैं "स्व" कॉलम हेडर पर क्लिक करने के लिए अगली विंडो में सलाह देता हूं, अन्यथा यह दर्शाता है कि "मुख्य ()" सबसे अधिक समय लेने वाला कार्य है। "स्व" दिखाता है कि प्रत्येक फ़ंक्शन ने खुद पर कितना समय लिया, न कि आश्रितों के साथ मिलकर।


9
अब किसी कारण पर callgrind.out। * फाइलें हमेशा खाली थीं। Callgrind_control -d को निष्पादित करना डिस्क में डेटा के डंप को मजबूर करने के लिए उपयोगी था।
टुन्नू शमूएल

3
नहीं कर सकते। मेरे सामान्य संदर्भ पूरे MySQL या PHP या कुछ इसी तरह की बड़ी चीज़ जैसे हैं। अक्सर यह भी नहीं पता कि मैं पहले क्या अलग करना चाहता हूं।
टुन्नू शमूएल

2
या मेरे मामले में मेरा कार्यक्रम वास्तव में एलआरयू कैश में डेटा का एक गुच्छा लोड करता है, और मैं चाहता हूं कि वह प्रोफाइल न करे। इसलिए मैं स्टार्टअप पर कैश के एक उपसमूह को लोड करता हूं, और केवल उस डेटा का उपयोग करके कोड को प्रोफाइल करता हूं (ओएस + सीपीयू को मेरे कैश के भीतर मेमोरी उपयोग का प्रबंधन करने देता है)। यह काम करता है, लेकिन उस कोड को लोड करना धीमा है और कोड भर में सीपीयू गहन है जिसे मैं एक अलग संदर्भ में प्रोफाइल करने की कोशिश कर रहा हूं, इसलिए कॉलगर्ल बुरी तरह से प्रदूषित परिणाम पैदा करता है।
कोड एबोमिनेटर

2
CALLGRIND_TOGGLE_COLLECTप्रोग्राम को संग्रह को सक्षम / अक्षम करने के लिए भी है; देखें stackoverflow.com/a/13700817/288875
आंद्रे होल्ज़नर

1
वाह, मुझे नहीं पता था कि यह अस्तित्व में है, धन्यवाद!
विंसेंट फोरमंड

59

यह नाज़गोब के गैर-जवाब का जवाब है

मैं पिछले कुछ दिनों से Gprof का उपयोग कर रहा हूं और पहले से ही तीन महत्वपूर्ण सीमाएं पा चुका हूं, जिनमें से एक को मैंने कहीं और (अभी तक) दस्तावेज नहीं देखा है:

  1. यह बहु-थ्रेडेड कोड पर ठीक से काम नहीं करता है, जब तक कि आप वर्कअराउंड का उपयोग नहीं करते हैं

  2. कॉल ग्राफ फ़ंक्शन पॉइंटर्स द्वारा भ्रमित हो जाता है। उदाहरण: मेरे पास एक फ़ंक्शन है multithread()जो मुझे एक निर्दिष्ट सरणी (दोनों तर्कों के रूप में पारित) पर एक निर्दिष्ट फ़ंक्शन को बहु-थ्रेड करने में सक्षम बनाता है। हालांकि, ग्रिफ़िट सभी विचारों multithread()को बच्चों में बिताए गए कंप्यूटिंग समय के उद्देश्यों के बराबर मानता है । कुछ कार्यों के बाद से मैं multithread()दूसरों की तुलना में अधिक समय लेने के लिए गुजरता हूं, मेरे कॉल ग्राफ़ ज्यादातर बेकार हैं। (अगर थ्रेडिंग के बारे में सोच रहे लोग यहां मुद्दा है: नहीं, multithread()वैकल्पिक रूप से, और इस मामले में किया, सब कुछ क्रमिक रूप से केवल कॉलिंग थ्रेड पर चला सकते हैं)।

  3. यह यहां कहा गया है कि "... संख्या के कॉल आंकड़े गिनती के द्वारा प्राप्त किए जाते हैं, नमूना नहीं। वे पूरी तरह से सटीक हैं ..."। फिर भी मैं अपने कॉल ग्राफ को मुझे 5345859132 + 784984078 पर कॉल-आँकड़े के रूप में अपने सबसे तथाकथित फ़ंक्शन में देता हूँ, जहाँ पहला नंबर डायरेक्ट कॉल करने वाला है, और दूसरा रिकर्सिव कॉल (जो सभी अपने आप में हैं)। चूंकि यह निहित है कि मेरे पास एक बग था, मैंने कोड में लंबे (64-बिट) काउंटरों को रखा और फिर से वही रन किया। मेरी गिनती: 5345859132 प्रत्यक्ष, और 78094395406 स्व-पुनरावर्ती कॉल। वहाँ बहुत सारे अंक हैं, इसलिए मैं पुनरावर्ती कॉलों को इंगित करूंगा जो मैं मापता हूं 78bn, बनाम 784 मी ग्रिट से: 100 का एक कारक। दोनों रन एकल थ्रेडेड और अडॉप्ट किए गए कोड थे, एक संकलित -gऔर दूसरा -pg

यह GNU Gprof ( GNB Binutils for Debian) 2.18.0.20080103 64-बिट डेबियन लेनी के तहत चल रहा था, अगर वह किसी की मदद करता है।


हां, यह सैंपलिंग करता है, लेकिन नंबर-ऑफ-कॉल के आंकड़ों के लिए नहीं। दिलचस्प बात यह है कि आपके लिंक के बाद, आखिरकार मैंने अपने पोस्ट, नए URL: sourceware.org/binutils/docs/gprof/… से जुड़े मैनुअल पेज के एक अपडेटेड वर्जन की ओर ले गया, यह मेरे उत्तर के भाग (iii) में बोली को दोहराता है, लेकिन यह भी कहता है कि "बहु-थ्रेडेड अनुप्रयोगों में, या एकल थ्रेडेड एप्लिकेशन जो बहु-थ्रेडेड लाइब्रेरी के साथ लिंक करते हैं, काउंट केवल नियतात्मक होते हैं यदि गिनती फ़ंक्शन थ्रेड-सुरक्षित है। (नोट: सावधान रहें कि ग्लिबैक में mcount काउंटिंग फ़ंक्शन थ्रेड नहीं है। -सुरक्षित)। "
Rob_before_edits 4

यह मेरे लिए स्पष्ट नहीं है अगर यह (iii) में मेरा परिणाम बताता है। मेरा कोड -lpreadread -lm से जुड़ा हुआ था और दोनों ने "pthread_t * thr" और "pthread_mutex_t nextLock = PTHREAD_MUTEX_INITIALIZER" स्टेटिक वैरिएबल को तब भी घोषित किया जब यह सिंगल थ्रेडेड चल रहा था। मैं आमतौर पर मानता हूँ कि "मल्टी-थ्रेडेड लाइब्रेरीज़ के साथ लिंक" का अर्थ है वास्तव में उन पुस्तकालयों का उपयोग करना, और इससे भी अधिक हद तक, लेकिन मैं गलत हो सकता है!
Rob_before_edits

23

Valgrind, callgrind और kcachegrind का उपयोग करें:

valgrind --tool=callgrind ./(Your binary)

callgrind.out.x उत्पन्न करता है। इसे kcachegrind का उपयोग करके पढ़ें।

Gprof (add -pg) का प्रयोग करें:

cc -o myprog myprog.c utils.c -g -pg 

(मल्टी-थ्रेड्स, फंक्शन पॉइंटर्स के लिए इतना अच्छा नहीं)

Google-perftools का उपयोग करें:

समय के नमूने का उपयोग करता है, I / O और CPU अड़चनें सामने आती हैं।

इंटेल वीट्यून सबसे अच्छा है (शैक्षिक उद्देश्यों के लिए मुफ्त)।

अन्य: AMD Codeanalyst (AMD कोड XL के साथ बदल दिया गया), OProfile, 'perf' टूल (apt-get install linux-tools)


10

C ++ प्रोफाइलिंग तकनीकों का सर्वेक्षण

इस उत्तर में, मैं कुछ अलग-अलग सरल परीक्षण कार्यक्रमों का विश्लेषण करने के लिए कई अलग-अलग साधनों का उपयोग करूँगा, ताकि उन साधनों की तुलना कैसे की जा सके।

निम्नलिखित परीक्षण कार्यक्रम बहुत सरल है और निम्न कार्य करता है:

  • mainकॉल fastऔर maybe_slow3 बार, एक maybe_slowकॉल धीमी हो रही है

    धीमी गति से कॉल maybe_slow10x लंबी है, और रनटाइम पर हावी हो जाती है अगर हम चाइल्ड फ़ंक्शन को कॉल पर विचार करते हैं common। आदर्श रूप से, प्रोफाइलिंग टूल हमें विशिष्ट धीमे कॉल पर इंगित करने में सक्षम होगा।

  • दोनों fastऔर maybe_slowकॉल करें common, जो कार्यक्रम के निष्पादन के थोक के लिए खाता है

  • कार्यक्रम इंटरफ़ेस है:

    ./main.out [n [seed]]

    और कार्यक्रम O(n^2)कुल में लूप करता है । seedबस रनटाइम को प्रभावित किए बिना अलग-अलग आउटपुट प्राप्त करना है।

main.c

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

uint64_t __attribute__ ((noinline)) common(uint64_t n, uint64_t seed) {
    for (uint64_t i = 0; i < n; ++i) {
        seed = (seed * seed) - (3 * seed) + 1;
    }
    return seed;
}

uint64_t __attribute__ ((noinline)) fast(uint64_t n, uint64_t seed) {
    uint64_t max = (n / 10) + 1;
    for (uint64_t i = 0; i < max; ++i) {
        seed = common(n, (seed * seed) - (3 * seed) + 1);
    }
    return seed;
}

uint64_t __attribute__ ((noinline)) maybe_slow(uint64_t n, uint64_t seed, int is_slow) {
    uint64_t max = n;
    if (is_slow) {
        max *= 10;
    }
    for (uint64_t i = 0; i < max; ++i) {
        seed = common(n, (seed * seed) - (3 * seed) + 1);
    }
    return seed;
}

int main(int argc, char **argv) {
    uint64_t n, seed;
    if (argc > 1) {
        n = strtoll(argv[1], NULL, 0);
    } else {
        n = 1;
    }
    if (argc > 2) {
        seed = strtoll(argv[2], NULL, 0);
    } else {
        seed = 0;
    }
    seed += maybe_slow(n, seed, 0);
    seed += fast(n, seed);
    seed += maybe_slow(n, seed, 1);
    seed += fast(n, seed);
    seed += maybe_slow(n, seed, 0);
    seed += fast(n, seed);
    printf("%" PRIX64 "\n", seed);
    return EXIT_SUCCESS;
}

gprof

ग्रिफ़िट को इंस्ट्रूमेंटेशन के साथ सॉफ्टवेयर को फिर से स्थापित करने की आवश्यकता होती है, और यह उस इंस्ट्रूमेंटेशन के साथ एक नमूना दृष्टिकोण का भी उपयोग करता है। इसलिए यह सटीकता के बीच एक संतुलन बनाता है (नमूना हमेशा पूरी तरह से सटीक नहीं होता है और कार्यों को छोड़ सकता है) और निष्पादन मंदी (इंस्ट्रूमेंटेशन और नमूनाकरण अपेक्षाकृत तेज़ तकनीकें हैं जो निष्पादन को बहुत धीमा नहीं करती हैं)।

Gprof में GCC / binutils बनाया गया है, इसलिए हमें केवल इतना करना है -pgकि आप gitable को सक्षम करने के विकल्प के साथ संकलित करें। हम तब प्रोग्राम को सामान्य रूप से एक आकार सीएलआई पैरामीटर के साथ चलाते हैं जो कुछ सेकंड की उचित अवधि ( 10000) का उत्पादन करता है :

gcc -pg -ggdb3 -O3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
time ./main.out 10000

शैक्षिक कारणों के लिए, हम सक्षम किए बिना अनुकूलन के साथ एक रन भी करेंगे। ध्यान दें कि यह व्यवहार में बेकार है, क्योंकि आप आमतौर पर केवल अनुकूलित कार्यक्रम के प्रदर्शन का अनुकूलन करने के बारे में परवाह करते हैं:

gcc -pg -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out 10000

सबसे पहले, timeहमें बताता है कि निष्पादन के समय के साथ और बिना -pgसमान थे, जो महान है: कोई मंदी नहीं! मैंने हालांकि जटिल सॉफ्टवेयर पर 2x - 3x की मंदी के खातों को देखा है, जैसे कि इस टिकट में दिखाया गया है

क्योंकि हमने संकलित किया है -pg, प्रोग्राम को चलाने से एक फ़ाइल gmon.outफ़ाइल तैयार होती है जिसमें प्रोफाइलिंग डेटा होता है।

हम उस फ़ाइल का ग्राफ़िकल gprof2dotरूप से निरीक्षण कर सकते हैं जैसा कि पूछा गया है: क्या यह संभावित परिणामों के चित्रमय प्रतिनिधित्व को प्राप्त करना संभव है?

sudo apt install graphviz
python3 -m pip install --user gprof2dot
gprof main.out > main.gprof
gprof2dot < main.gprof | dot -Tsvg -o output.svg

यहां, gprofटूल gmon.outट्रेस जानकारी को पढ़ता है , और एक मानव पठनीय रिपोर्ट उत्पन्न करता है main.gprof, जो gprof2dotतब एक ग्राफ़ उत्पन्न करने के लिए पढ़ता है।

Gprof2dot का स्रोत यहां है: https://github.com/jrfonseca/gprof2dot

हम -O0रन के लिए निम्नलिखित का पालन करते हैं:

यहां छवि विवरण दर्ज करें

और -O3रन के लिए:

यहां छवि विवरण दर्ज करें

-O0उत्पादन काफी आत्म व्याख्यात्मक है। उदाहरण के लिए, यह दर्शाता है कि 3 maybe_slowकॉल और उनके बच्चे कॉल कुल रनटाइम का 97.56% लेते हैं, हालांकि maybe_slowबच्चों के बिना खुद का निष्पादन कुल निष्पादन समय का 0.00% है, अर्थात उस फ़ंक्शन में खर्च किए गए लगभग सभी समय पर खर्च किया गया था बच्चा कहता है।

TODO: आउटपुट mainसे क्यों गायब है -O3, भले ही मैं इसे btGDB में देख सकता हूं ? जीप्रोफ आउटपुट से मिसिंग फंक्शन मुझे लगता है कि यह इसलिए है क्योंकि इसके संकलित इंस्ट्रूमेंटेशन के अलावा ग्राइपिट भी सैंपलिंग आधारित है, और -O3 mainयह सिर्फ बहुत तेज़ है और कोई सैंपल नहीं मिला है।

मैं पीएनजी के बजाय एसवीजी आउटपुट का चयन करता हूं क्योंकि एसवीजी Ctrl + F के साथ खोजा जा सकता है और फ़ाइल का आकार लगभग 10x छोटा हो सकता है। इसके अलावा, उत्पन्न छवि की चौड़ाई और ऊंचाई जटिल सॉफ़्टवेयर के लिए हजारों पिक्सेल के दसियों के साथ विनम्र हो सकती है, और eogPNGs के लिए उस मामले में GNOME 3.28.1 बग्स, जबकि SVGs मेरे ब्राउज़र द्वारा स्वचालित रूप से खुल जाते हैं। जिम्प 2.8 हालांकि अच्छी तरह से काम किया, यह भी देखें:

लेकिन फिर भी, आप जो चाहते हैं उसे खोजने के लिए छवि को बहुत चारों ओर खींच रहे हैं, उदाहरण के लिए इस टिकट से लिए गए "वास्तविक" सॉफ़्टवेयर उदाहरण से इस छवि को देखें :

यहां छवि विवरण दर्ज करें

क्या आप उन सभी छोटी अनसुलझी स्पेगेटी लाइनों के साथ एक दूसरे पर जाने वाली सबसे महत्वपूर्ण कॉल स्टैक आसानी से पा सकते हैं? वहाँ बेहतर dotविकल्प हो सकता है मुझे यकीन है, लेकिन मैं अब वहां नहीं जाना चाहता। हमें वास्तव में इसके लिए एक उचित समर्पित दर्शक चाहिए, लेकिन मुझे अभी तक यह नहीं मिला है:

हालाँकि आप उन समस्याओं को थोड़ा कम करने के लिए रंगीन मानचित्र का उपयोग कर सकते हैं। उदाहरण के लिए, पिछली विशाल छवि पर, मैंने आखिरकार बाईं ओर महत्वपूर्ण पथ खोजने में कामयाबी हासिल की जब मैंने शानदार कटौती की जो कि हरे रंग के बाद आती है, उसके बाद अंत में गहरा और गहरा नीला होता है।

वैकल्पिक रूप से, हम gprofबिल्ट-इन बिनुटिल्स टूल के टेक्स्ट आउटपुट का भी निरीक्षण कर सकते हैं, जिसे हमने पहले बचाया था:

cat main.gprof

डिफ़ॉल्ट रूप से, यह एक अत्यंत क्रिया आउटपुट उत्पन्न करता है जो बताता है कि आउटपुट डेटा का क्या अर्थ है। चूंकि मैं इससे बेहतर व्याख्या नहीं कर सकता, इसलिए मैं आपको इसे स्वयं पढ़ने दूंगा।

एक बार जब आप डेटा आउटपुट प्रारूप को समझ जाते हैं, तो आप -bविकल्प के साथ ट्यूटोरियल के बिना सिर्फ डेटा दिखाने के लिए वर्बोसिटी को कम कर सकते हैं :

gprof -b main.out

हमारे उदाहरण में, आउटपुट -O0निम्न थे :

Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls   s/call   s/call  name    
100.35      3.67     3.67   123003     0.00     0.00  common
  0.00      3.67     0.00        3     0.00     0.03  fast
  0.00      3.67     0.00        3     0.00     1.19  maybe_slow

            Call graph


granularity: each sample hit covers 2 byte(s) for 0.27% of 3.67 seconds

index % time    self  children    called     name
                0.09    0.00    3003/123003      fast [4]
                3.58    0.00  120000/123003      maybe_slow [3]
[1]    100.0    3.67    0.00  123003         common [1]
-----------------------------------------------
                                                 <spontaneous>
[2]    100.0    0.00    3.67                 main [2]
                0.00    3.58       3/3           maybe_slow [3]
                0.00    0.09       3/3           fast [4]
-----------------------------------------------
                0.00    3.58       3/3           main [2]
[3]     97.6    0.00    3.58       3         maybe_slow [3]
                3.58    0.00  120000/123003      common [1]
-----------------------------------------------
                0.00    0.09       3/3           main [2]
[4]      2.4    0.00    0.09       3         fast [4]
                0.09    0.00    3003/123003      common [1]
-----------------------------------------------

Index by function name

   [1] common                  [4] fast                    [3] maybe_slow

और इसके लिए -O3:

Flat profile:

Each sample counts as 0.01 seconds.
  %   cumulative   self              self     total           
 time   seconds   seconds    calls  us/call  us/call  name    
100.52      1.84     1.84   123003    14.96    14.96  common

            Call graph


granularity: each sample hit covers 2 byte(s) for 0.54% of 1.84 seconds

index % time    self  children    called     name
                0.04    0.00    3003/123003      fast [3]
                1.79    0.00  120000/123003      maybe_slow [2]
[1]    100.0    1.84    0.00  123003         common [1]
-----------------------------------------------
                                                 <spontaneous>
[2]     97.6    0.00    1.79                 maybe_slow [2]
                1.79    0.00  120000/123003      common [1]
-----------------------------------------------
                                                 <spontaneous>
[3]      2.4    0.00    0.04                 fast [3]
                0.04    0.00    3003/123003      common [1]
-----------------------------------------------

Index by function name

   [1] common

प्रत्येक अनुभाग के लिए एक बहुत ही त्वरित सारांश के रूप में:

                0.00    3.58       3/3           main [2]
[3]     97.6    0.00    3.58       3         maybe_slow [3]
                3.58    0.00  120000/123003      common [1]

फ़ंक्शन के आसपास केंद्र जो इंडेंटेड ( maybe_flow) छोड़ दिए गए हैं । [3]उस फ़ंक्शन की आईडी है। फ़ंक्शन के ऊपर, इसके कॉलर्स हैं, और इसके नीचे कैलिस हैं।

इसके लिए -O3, यहां देखें कि चित्रमय आउटपुट में क्या है maybe_slowऔर fastएक ज्ञात माता-पिता नहीं है, जो कि प्रलेखन का <spontaneous>मतलब है।

मुझे यकीन नहीं है कि वहाँ एक अच्छा तरीका है लाइन-बाय-लाइन प्रोफाइलिंग को ग्रिट के साथ करना है: `gprof` समय कोड की विशेष लाइनों में बिताया

वेलग्रिंड कॉलग्रिंड

valgrind वर्चुअल मशीन के माध्यम से प्रोग्राम चलाता है। यह प्रोफाइलिंग को बहुत सटीक बनाता है, लेकिन यह प्रोग्राम की एक बहुत बड़ी मंदी भी पैदा करता है। मैंने पहले भी kcachegrind पर उल्लेख किया है: उपकरण एक चित्रमय फ़ंक्शन कोड के ग्राफ़ को प्राप्त करने के लिए

कॉलग्रिंड प्रोफाइल कोड के लिए वैलग्राइंड का उपकरण है और kcachegrind एक केडीई प्रोग्राम है जो कैशेग्रिंड आउटपुट की कल्पना कर सकता है।

पहले हमें -pgसामान्य संकलन पर वापस जाने के लिए ध्वज को निकालना होगा , अन्यथा रन वास्तव में विफल हो जाता है Profiling timer expired, और हां, यह इतना सामान्य है कि मैंने किया और इसके लिए एक स्टैक ओवरफ्लो प्रश्न था।

इसलिए हम संकलित करते हैं:

sudo apt install kcachegrind valgrind
gcc -ggdb3 -O3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
time valgrind --tool=callgrind valgrind --dump-instr=yes \
  --collect-jumps=yes ./main.out 10000

मैं सक्षम करता हूं --dump-instr=yes --collect-jumps=yesक्योंकि यह उन सूचनाओं को भी डंप करता है जो हमें एक अपेक्षाकृत छोटे जोड़े गए ओवरहेड लागत पर प्रदर्शन के प्रति असेंबली लाइन टूटने को देखने में सक्षम बनाता है।

बल्ले से, timeहमें बताता है कि कार्यक्रम को निष्पादित करने में 29.5 सेकंड लगे, इसलिए हमारे पास इस उदाहरण पर लगभग 15x की मंदी थी। जाहिर है, यह मंदी बड़े काम के बोझ के लिए एक गंभीर सीमा होने जा रही है। यहां वर्णित "वास्तविक विश्व सॉफ्टवेयर उदाहरण" पर , मैंने 80x की मंदी देखी।

रन मेरे मामले में callgrind.out.<pid>उदाहरण के लिए एक प्रोफाइल डेटा फ़ाइल उत्पन्न करता है callgrind.out.8554। हम उस फ़ाइल को इसके साथ देखते हैं:

kcachegrind callgrind.out.8554

जो एक जीयूआई दिखाता है जिसमें टेक्स्ट ग्राइप आउटपुट के समान डेटा होता है:

यहां छवि विवरण दर्ज करें

इसके अलावा, अगर हम नीचे दाईं ओर "कॉल ग्राफ़" टैब पर जाते हैं, तो हमें एक कॉल ग्राफ़ दिखाई देता है, जिसे हम राइट क्लिक करके निर्यात कर सकते हैं, ताकि सफेद सीमा के अनुचित मात्रा के साथ निम्नलिखित छवि प्राप्त कर सकें :-)

यहां छवि विवरण दर्ज करें

मुझे लगता fastहै कि उस ग्राफ़ पर नहीं दिख रहा है क्योंकि kcachegrind ने विज़ुअलाइज़ेशन को सरल बना दिया होगा क्योंकि उस कॉल में बहुत कम समय लगता है, यह संभवतः वह व्यवहार होगा जो आप एक वास्तविक प्रोग्राम पर चाहते हैं। राइट क्लिक मेनू में ऐसे नोड्स को खींचने के लिए नियंत्रित करने के लिए कुछ सेटिंग्स हैं, लेकिन मैं इसे एक त्वरित प्रयास के बाद इतनी कम कॉल दिखाने के लिए नहीं मिला। अगर मैं fastबाईं विंडो पर क्लिक करता हूं , तो यह एक कॉल ग्राफ दिखाता है fast, जिससे स्टैक वास्तव में कैप्चर किया गया था। किसी को अभी तक पूर्ण ग्राफ़ कॉल ग्राफ़ दिखाने का कोई तरीका नहीं मिला था : कॉलग्रिंड शो करें सभी फ़ंक्शन कॉल kcachegrat कॉल ग्राफ़ में दिखाएँ

TODO जटिल C ++ सॉफ्टवेयर पर, मुझे कुछ प्रकार की प्रविष्टियाँ दिखाई देती हैं <cycle N>, उदाहरण के लिए, <cycle 11>जहाँ मैं फ़ंक्शन नामों की अपेक्षा करूँगा, इसका क्या मतलब है? मैंने देखा कि वहाँ "टॉगल डिटेक्शन" बटन है जो चालू और बंद है, लेकिन इसका क्या मतलब है?

perf से linux-tools

perfविशेष रूप से लिनक्स कर्नेल सैंपलिंग तंत्र का उपयोग करने लगता है। यह सेटअप करने के लिए बहुत सरल है, लेकिन यह भी पूरी तरह से सटीक नहीं है।

sudo apt install linux-tools
time perf record -g ./main.out 10000

इसने 0.2s को निष्पादन में जोड़ा है, इसलिए हम समय के हिसाब से ठीक हैं, लेकिन मैं अभी भी बहुत दिलचस्पी नहीं देख रहा हूं, commonकीबोर्ड के मुख्य तीर के साथ नोड का विस्तार करने के बाद :

Samples: 7K of event 'cycles:uppp', Event count (approx.): 6228527608     
  Children      Self  Command   Shared Object     Symbol                  
-   99.98%    99.88%  main.out  main.out          [.] common              
     common                                                               
     0.11%     0.11%  main.out  [kernel]          [k] 0xffffffff8a6009e7  
     0.01%     0.01%  main.out  [kernel]          [k] 0xffffffff8a600158  
     0.01%     0.00%  main.out  [unknown]         [k] 0x0000000000000040  
     0.01%     0.00%  main.out  ld-2.27.so        [.] _dl_sysdep_start    
     0.01%     0.00%  main.out  ld-2.27.so        [.] dl_main             
     0.01%     0.00%  main.out  ld-2.27.so        [.] mprotect            
     0.01%     0.00%  main.out  ld-2.27.so        [.] _dl_map_object      
     0.01%     0.00%  main.out  ld-2.27.so        [.] _xstat              
     0.00%     0.00%  main.out  ld-2.27.so        [.] __GI___tunables_init
     0.00%     0.00%  main.out  [unknown]         [.] 0x2f3d4f4944555453  
     0.00%     0.00%  main.out  [unknown]         [.] 0x00007fff3cfc57ac  
     0.00%     0.00%  main.out  ld-2.27.so        [.] _start              

तो फिर मैं यह देखने के लिए -O0प्रोग्राम को बेंचमार्क करने की कोशिश करता हूं कि क्या कुछ दिखाता है, और केवल अब, आखिर में, क्या मुझे कॉल ग्राफ़ दिखाई देता है:

Samples: 15K of event 'cycles:uppp', Event count (approx.): 12438962281   
  Children      Self  Command   Shared Object     Symbol                  
+   99.99%     0.00%  main.out  [unknown]         [.] 0x04be258d4c544155  
+   99.99%     0.00%  main.out  libc-2.27.so      [.] __libc_start_main   
-   99.99%     0.00%  main.out  main.out          [.] main                
   - main                                                                 
      - 97.54% maybe_slow                                                 
           common                                                         
      - 2.45% fast                                                        
           common                                                         
+   99.96%    99.85%  main.out  main.out          [.] common              
+   97.54%     0.03%  main.out  main.out          [.] maybe_slow          
+    2.45%     0.00%  main.out  main.out          [.] fast                
     0.11%     0.11%  main.out  [kernel]          [k] 0xffffffff8a6009e7  
     0.00%     0.00%  main.out  [unknown]         [k] 0x0000000000000040  
     0.00%     0.00%  main.out  ld-2.27.so        [.] _dl_sysdep_start    
     0.00%     0.00%  main.out  ld-2.27.so        [.] dl_main             
     0.00%     0.00%  main.out  ld-2.27.so        [.] _dl_lookup_symbol_x 
     0.00%     0.00%  main.out  [kernel]          [k] 0xffffffff8a600158  
     0.00%     0.00%  main.out  ld-2.27.so        [.] mmap64              
     0.00%     0.00%  main.out  ld-2.27.so        [.] _dl_map_object      
     0.00%     0.00%  main.out  ld-2.27.so        [.] __GI___tunables_init
     0.00%     0.00%  main.out  [unknown]         [.] 0x552e53555f6e653d  
     0.00%     0.00%  main.out  [unknown]         [.] 0x00007ffe1cf20fdb  
     0.00%     0.00%  main.out  ld-2.27.so        [.] _start              

TODO: -O3फांसी पर क्या हुआ ? क्या यह केवल इतना है maybe_slowऔर fastबहुत तेज़ थे और कोई नमूना नहीं मिला? क्या यह -O3बड़े कार्यक्रमों पर अच्छी तरह से काम करता है जिन्हें निष्पादित करने में अधिक समय लगता है? क्या मुझे कुछ सीएलआई विकल्प याद आया? मुझे -Fहर्ट्ज में नमूना आवृत्ति को नियंत्रित करने के बारे में पता चला , लेकिन मैंने इसे डिफ़ॉल्ट रूप से अधिकतम अनुमति के लिए बदल दिया -F 39500(इसके साथ बढ़ाया जा सकता है sudo) और मुझे अभी भी स्पष्ट कॉल नहीं दिख रहे हैं।

एक अच्छी बात है perfब्रेंडन ग्रेग का फ्लेमग्राफ टूल है जो कॉल स्टैक के समय को बहुत साफ तरीके से प्रदर्शित करता है जो आपको बड़ी कॉल को जल्दी से देखने की अनुमति देता है। यह टूल यहां उपलब्ध है: https://github.com/brendangregg/FlameGraph और इसका पूर्ण ट्यूटोरियल पर भी उल्लेख किया गया है: http://www.brendangregg.com/perf.html#FlameGraphs जब मैं perfबिना भाग sudoगया ERROR: No stack counts foundतो मुझे इसके लिए मिला अब मैं इसके साथ करूँगा sudo:

git clone https://github.com/brendangregg/FlameGraph
sudo perf record -F 99 -g -o perf_with_stack.data ./main.out 10000
sudo perf script -i perf_with_stack.data | FlameGraph/stackcollapse-perf.pl | FlameGraph/flamegraph.pl > flamegraph.svg

लेकिन इस तरह के एक सरल कार्यक्रम में आउटपुट को समझना बहुत आसान नहीं है, क्योंकि हम आसानी से न तो उस ग्राफ पर देख सकते हैं और न maybe_slowही fast:

यहां छवि विवरण दर्ज करें

अधिक जटिल उदाहरण पर यह स्पष्ट हो जाता है कि ग्राफ़ का क्या अर्थ है:

यहां छवि विवरण दर्ज करें

TODO [unknown]उस उदाहरण में कार्यों का एक लॉग है , ऐसा क्यों है?

एक और परिपूर्ण जीयूआई इंटरफेस जो इसके लायक हो सकता है:

  • ग्रहण ट्रेस कम्पास प्लगइन: https://www.eclipse.org/tracecompass/

    लेकिन इसका नकारात्मक पहलू यह है कि आपको सबसे पहले डेटा को कॉमन ट्रेस फॉर्मेट में बदलना होगा, जिसके साथ किया जा सकता है perf data --to-ctf , लेकिन इसे बिल्ड समय पर सक्षम करने की आवश्यकता है / perfनए पर्याप्त होने चाहिए , जिनमें से किसी एक के लिए पूर्णता की स्थिति नहीं है। उबुन्टु 18.04

  • https://github.com/KDAB/hotspot

    इसका नकारात्मक पक्ष यह है कि उबंटू पैकेज नहीं है, और इसके निर्माण के लिए Qt 5.10 की आवश्यकता है जबकि Ubuntu 18.04 Qt 5.9 पर है।

gperftools

पहले "Google प्रदर्शन उपकरण" कहा जाता था, स्रोत: https://github.com/gperftools/gperftools नमूना आधारित।

पहले gperftools स्थापित करें:

sudo apt install google-perftools

फिर, हम gperftools CPU प्रोफाइलर को दो तरह से सक्षम कर सकते हैं: रनटाइम पर, या बिल्ड टाइम पर।

रनटाइम के दौरान, हमें LD_PRELOADइंगित करने के लिए सेट करना होगा libprofiler.so, जिसे आप locate libprofiler.soमेरे सिस्टम पर देख सकते हैं , जैसे:

gcc -ggdb3 -O3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libprofiler.so \
  CPUPROFILE=prof.out ./main.out 10000

वैकल्पिक रूप से, हम लायब्रेरी को लिंक टाइम पर बना सकते हैं, LD_PRELOADरनटाइम में पासिंग को वितरित करते हुए:

gcc -Wl,--no-as-needed,-lprofiler,--as-needed -ggdb3 -O3 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
CPUPROFILE=prof.out ./main.out 10000

यह भी देखें: gperftools - प्रोफ़ाइल फ़ाइल को डंप नहीं किया गया

इस डेटा को देखने का सबसे अच्छा तरीका यह है कि मैं pprof आउटपुट को उसी प्रारूप में बना सकता हूं जिसे kcachegrind इनपुट के रूप में लेता है (हां, Valgrind-project-दर्शक-उपकरण) और देखने के लिए kcachegrind का उपयोग करें:

google-pprof --callgrind main.out prof.out  > callgrind.out
kcachegrind callgrind.out

उन विधियों में से किसी एक के साथ चलने के बाद, हमें prof.outआउटपुट के रूप में एक प्रोफाइल डेटा फ़ाइल मिलती है । हम उस फ़ाइल को एसवीजी के रूप में रेखांकन के साथ देख सकते हैं:

google-pprof --web main.out prof.out

यहां छवि विवरण दर्ज करें

जो अन्य उपकरणों की तरह एक परिचित कॉल ग्राफ के रूप में देता है, लेकिन सेकंड के बजाय नमूनों की संख्या की क्लंकी इकाई के साथ।

वैकल्पिक रूप से, हम कुछ पाठ्य सामग्री भी प्राप्त कर सकते हैं:

google-pprof --text main.out prof.out

जो देता है:

Using local file main.out.
Using local file prof.out.
Total: 187 samples
     187 100.0% 100.0%      187 100.0% common
       0   0.0% 100.0%      187 100.0% __libc_start_main
       0   0.0% 100.0%      187 100.0% _start
       0   0.0% 100.0%        4   2.1% fast
       0   0.0% 100.0%      187 100.0% main
       0   0.0% 100.0%      183  97.9% maybe_slow

इसे भी देखें: google perf टूल का उपयोग कैसे करें

Ubuntu 18.04 में परीक्षण किया गया, gprof2dot 2019.11.30, valgrind 3.13.0, perf 4.15.18, Linux कर्नेल 4.15.0, FlameGraph 1a0dc6985aad06e76857f2a354bd5ba0c9ce96b, gperftools 2.5-2।


2
डिफ़ॉल्ट परफ़ॉर्म रिकॉर्ड द्वारा फ्रेम पॉइंटर रजिस्टर का उपयोग किया जाता है। आधुनिक संकलक फ्रेम पते को रिकॉर्ड नहीं करते हैं और इसके बजाय एक सामान्य उद्देश्य के रूप में रजिस्टर का उपयोग करते हैं। विकल्प को -fno-omit-frame-pointerध्वज के साथ संकलित करना या एक अलग विकल्प का उपयोग करना है: अपने परिदृश्य के साथ --call-graph "dwarf"या --call-graph "lbr"उसके आधार पर रिकॉर्ड करें।
जॉर्ज बेलन

5

एकल-थ्रेडेड प्रोग्राम्स के लिए आप igprof , द इग्नाइनोमस प्रोइलर: https://igprof.org/ का उपयोग कर सकते हैं ।

यह एक नमूना प्रोफाइलर है, की पंक्तियों के साथ ... लंबे ... माइक डनलैवी द्वारा उत्तर दिया गया, जो उपहार को परिणामी कॉल स्टैक ट्री में लपेट देगा, जो प्रत्येक फ़ंक्शन में खर्च किए गए समय या मेमोरी के साथ एनोटेट किया जाता है, या तो संचयी या प्रति-कार्य करते हैं।


यह दिलचस्प लग रहा है, लेकिन जीसीसी 9.2 के साथ संकलन करने में विफल रहता है। (डेबियन / सिड) मैंने जीथब पर एक मुद्दा बनाया।
बेसिल स्टारीनेविच

5

इसके अलावा उल्लेख के लायक हैं

  1. HPCToolkit ( http://hpctoolkit.org/ ) - ओपन-सोर्स, समानांतर कार्यक्रमों के लिए काम करता है और इसमें GUI होता है जिसके परिणाम देखने के लिए कई तरीके हैं
  2. Intel VTune ( https://software.intel.com/en-us/vtune ) - यदि आपके पास इंटेल कंपाइलर हैं तो यह बहुत अच्छा है
  3. TAU ( http://www.cs.uoregon.edu/research/tau/home.php )

मैंने HPCToolkit और VTune का उपयोग किया है और वे तम्बू में लंबे पोल को खोजने में बहुत प्रभावी हैं और आपके कोड को फिर से कनेक्ट करने की आवश्यकता नहीं है (सिवाय इसके कि -g का उपयोग करें -O या RelWithDebInfo प्रकार सार्थक निर्माण प्राप्त करने के लिए CMake में निर्माण करें) । मैंने सुना है TAU क्षमताओं में समान है।


4

ये दो विधियाँ हैं जिनका उपयोग मैं अपने कोड को तेज करने के लिए करता हूँ:

सीपीयू बाध्य अनुप्रयोगों के लिए:

  1. अपने कोड के संदिग्ध भागों की पहचान करने के लिए DEBUG मोड में एक प्रोफाइलर का उपयोग करें
  2. फिर RELEASE मोड पर जाएं और अपने कोड के संदिग्ध अनुभागों पर टिप्पणी करें (जब तक कि कुछ भी न हो) तब तक करें जब तक कि आप प्रदर्शन में परिवर्तन न देख लें।

I / O बाध्य अनुप्रयोगों के लिए:

  1. अपने कोड के संदिग्ध भागों की पहचान करने के लिए RELEASE मोड में एक प्रोफाइलर का उपयोग करें।

एनबी

यदि आपके पास प्रोफाइलर नहीं है, तो गरीब आदमी के प्रोफाइलर का उपयोग करें। अपना एप्लिकेशन डीबग करते समय पॉज़ करें। अधिकांश डेवलपर सूट टिप्पणी लाइन संख्या के साथ विधानसभा में टूटेंगे। आप सांख्यिकीय रूप से ऐसे क्षेत्र में उतरने की संभावना रखते हैं जो आपके अधिकांश सीपीयू चक्रों को खा रहा हो।

CPU के लिए, DEBUG मोड में प्रोफाइलिंग का कारण यह है कि यदि आपके RELEASE मोड में प्रोफाइलिंग की कोशिश की जाती है, तो कंपाइलर गणित को कम करने, लूप्स को वेक्टर करने, और इनलाइन फ़ंक्शंस करने जा रहा है, जो आपके कोड को अन-मैपेबल मेस में ग्लोब होने पर जमा करता है। एक अनपेक्षित गड़बड़ का मतलब है कि आपका प्रोफाइलर स्पष्ट रूप से यह पता लगाने में सक्षम नहीं होगा कि इतनी देर क्यों लग रही है क्योंकि विधानसभा अनुकूलन के तहत स्रोत कोड के अनुरूप नहीं हो सकती है । यदि आपको RELEASE मोड के प्रदर्शन (जैसे समय संवेदनशील) की आवश्यकता है, तो डिबग करने वाले सुविधाओं को अक्षम करें ताकि एक उपयोगी प्रदर्शन बनाए रखा जा सके।

I / O- बाउंड के लिए, प्रोफाइलर अभी भी RELEASE मोड में I / O ऑपरेशंस की पहचान कर सकता है क्योंकि I / O ऑपरेशंस या तो बाहरी रूप से एक साझा लाइब्रेरी से जुड़े होते हैं (ज्यादातर समय) या सबसे खराब स्थिति में, एक sys में परिणाम देगा- कॉल इंटरप्ट वेक्टर (जो प्रोफाइलर द्वारा आसानी से पहचानी जाने वाली भी है)।


2
+1 गरीब आदमी का तरीका सीपीयू बाउंड के लिए I / O बाउंड के समान ही काम करता है, और मैं DEUUG मोड में सभी प्रदर्शन ट्यूनिंग करने की सलाह देता हूं। जब आप ट्यूनिंग समाप्त कर लें, तब RELEASE को चालू करें। यदि प्रोग्राम आपके कोड में CPU-बाध्य है तो यह एक सुधार करेगा। यहां प्रक्रिया का एक कच्चा लेकिन छोटा वीडियो है।
माइक डनलवेई

3
मैं प्रदर्शन प्रोफाइलिंग के लिए DEBUG बिल्ड का उपयोग नहीं करूंगा। अक्सर मैंने देखा है कि डिबग मोड में प्रदर्शन के महत्वपूर्ण हिस्से पूरी तरह से रिलीज़ मोड में दूर हो जाते हैं। एक अन्य समस्या डिबग कोड में एज़र्ट्स का उपयोग है जो प्रदर्शन के लिए शोर जोड़ते हैं।
Gast128

3
क्या आपने मेरी पोस्ट को पूरा पढ़ा? "यदि आपको RAILASE मोड के प्रदर्शन (जैसे समय संवेदनशील) की आवश्यकता है, तो एक उपयोगी प्रदर्शन रखने के लिए आवश्यक डिबगर सुविधाओं को अक्षम करें", "उसके बाद RELEASE मोड पर जाएं और अपने कोड के संदिग्ध अनुभागों पर टिप्पणी करें (इसे कुछ भी नहीं देखें) जब तक आप इसे न देखें। प्रदर्शन में बदलाव? " मैंने कहा कि डिबग मोड में संभावित समस्या क्षेत्रों की जाँच करें और आपके द्वारा बताए गए नुकसान से बचने के लिए रिलीज़ मोड में उन समस्याओं को सत्यापित करें।
एसईओ

2

आप iprof लाइब्रेरी का उपयोग कर सकते हैं:

https://gitlab.com/Neurochrom/iprof

https://github.com/Neurochrom/iprof

यह क्रॉस-प्लेटफ़ॉर्म है और आपको अपने एप्लिकेशन के प्रदर्शन को वास्तविक समय में भी मापने की अनुमति नहीं देता है। आप इसे लाइव ग्राफ के साथ भी जोड़ सकते हैं। पूर्ण अस्वीकरण: मैं लेखक हूं।


2

आप लॉगिंग ढाँचे का उपयोग कर सकते हैं जैसे loguruकि इसमें टाइमस्टैम्प और कुल अपटाइम शामिल है जो प्रोफाइलिंग के लिए अच्छी तरह से उपयोग किया जा सकता है:


1

काम के दौरान हमारे पास एक बहुत अच्छा उपकरण है जो हमें निगरानी करने में मदद करता है कि हम शेड्यूलिंग के मामले में क्या चाहते हैं। यह कई बार उपयोगी रहा है।

यह C ++ में है और इसे आपकी आवश्यकताओं के अनुरूप होना चाहिए। दुर्भाग्य से मैं कोड, सिर्फ अवधारणाओं को साझा नहीं कर सकता। आप volatileटाइमस्टैम्प और इवेंट आईडी वाले "बड़े" बफर का उपयोग करते हैं जो आप पोस्टमार्टम को डंप कर सकते हैं या लॉगिंग सिस्टम को रोकने के बाद (और उदाहरण के लिए इसे फ़ाइल में डंप कर सकते हैं)।

आप सभी डेटा के साथ तथाकथित बड़े बफर को पुनः प्राप्त करते हैं और एक छोटा इंटरफ़ेस इसे पार्स करता है और नाम के साथ घटनाओं को दिखाता है (ऊपर / नीचे + मूल्य) जैसे ऑसिलोस्कोप रंगों ( .hppफाइल में कॉन्फ़िगर ) के साथ करता है ।

आप अपनी इच्छा पर पूरी तरह ध्यान केंद्रित करने के लिए उत्पन्न घटनाओं की मात्रा को अनुकूलित करते हैं। यह हमें सीपीयू की मात्रा का उपभोग करते समय कई मुद्दों को सुलझाने में मदद करता है जो हम प्रति सेकंड लॉग की गई घटनाओं की मात्रा के आधार पर चाहते थे।

आपको 3 फाइलें चाहिए:

toolname.hpp // interface
toolname.cpp // code
tool_events_id.hpp // Events ID

अवधारणा इस tool_events_id.hppतरह से घटनाओं को परिभाषित करना है:

// EVENT_NAME                         ID      BEGIN_END BG_COLOR NAME
#define SOCK_PDU_RECV_D               0x0301  //@D00301 BGEEAAAA # TX_PDU_Recv
#define SOCK_PDU_RECV_F               0x0302  //@F00301 BGEEAAAA # TX_PDU_Recv

आप कुछ कार्यों को भी परिभाषित करते हैं toolname.hpp:

#define LOG_LEVEL_ERROR 0
#define LOG_LEVEL_WARN 1
// ...

void init(void);
void probe(id,payload);
// etc

जहाँ भी आप कोड का उपयोग कर सकते हैं:

toolname<LOG_LEVEL>::log(EVENT_NAME,VALUE);

probeसमारोह में कुछ विधानसभा लाइनों का उपयोग करता है यथाशीघ्र घड़ी टाइमस्टैम्प पुनः प्राप्त करने के लिए और फिर बफर में एक प्रविष्टि सेट करता है। हमारे पास एक परमाणु वृद्धि भी है जो लॉग इवेंट को संग्रहीत करने के लिए सुरक्षित रूप से एक इंडेक्स ढूंढने के लिए है। बेशक बफर सर्कुलर है।

आशा है कि विचार नमूना कोड की कमी से बाधित नहीं है।


1

वास्तव में थोड़ा आश्चर्यचकित नहीं कई लोगों ने Google / बेंचमार्क के बारे में उल्लेख किया है , जबकि यह कोड के विशिष्ट क्षेत्र को पिन करने के लिए थोड़ा बोझिल है, खासकर अगर कोड आधार थोड़ा बड़ा है, लेकिन मुझे यह वास्तव में मददगार लगा जब संयोजन में उपयोग किया गयाcallgrind

IMHO उस टुकड़े की पहचान कर रहा है जो अड़चन पैदा कर रहा है। फिर भी मैं कोशिश करूंगा कि पहले निम्नलिखित प्रश्नों का उत्तर दूं और उसके आधार पर टूल चुनूं

  1. क्या मेरा एल्गोरिथ्म सही है?
  2. क्या ऐसे ताले हैं जो बोतल गर्दन साबित हो रहे हैं?
  3. क्या कोड का एक विशिष्ट खंड है जो अपराधी साबित हो रहा है?
  4. कैसे के बारे में IO, संभाला और अनुकूलित?

valgrindके संयोजन के साथ callrindऔर kcachegrindइसके बाद के संस्करण पर एक अच्छा अनुमान प्रदान करना चाहिए और एक बार यह स्थापित हो जाने के बाद कि कोड के कुछ खंड के साथ समस्याएं हैं, मेरा सुझाव है कि एक माइक्रो बेंच मार्क google benchmarkशुरू करने के लिए एक अच्छी जगह है।


1

-pgकोड का संकलन और लिंक करते समय ध्वज का उपयोग करें और निष्पादन योग्य फ़ाइल चलाएं। जबकि इस कार्यक्रम को निष्पादित किया जाता है, प्रोफाइल फाइल में डेटा जमा किया जाता है।
प्रोफाइलिंग दो अलग-अलग प्रकार की होती है

1- फ़्लैट प्रोफाइलिंग:
कमांड चलाने से gprog --flat-profile a.outआपको निम्नलिखित डेटा मिला
- फ़ंक्शन के लिए कुल समय का कितना प्रतिशत खर्च किया गया था,
- एक फ़ंक्शन में कितने सेकंड खर्च किए गए थे
- उप-फ़ंक्शंस के लिए कॉल को शामिल और छोड़कर, - कॉल,
- प्रति कॉल औसत समय।

2- ग्राफ
हमें gprof --graph a.outप्रत्येक फ़ंक्शन के लिए निम्न डेटा प्राप्त करने के लिए कमांड को प्रोफाइल करता है जिसमें शामिल हैं
- प्रत्येक अनुभाग में, एक फ़ंक्शन को एक इंडेक्स नंबर के साथ चिह्नित किया जाता है।
- फ़ंक्शन के ऊपर, फ़ंक्शन को कॉल करने वाले फ़ंक्शन की एक सूची है।
- फ़ंक्शन के नीचे, फ़ंक्शन की एक सूची है जिसे फ़ंक्शन द्वारा कहा जाता है।

अधिक जानकारी प्राप्त करने के लिए आप https://sourceware.org/binutils/docs-2.32/gprof/ पर देख सकते हैं


0

जैसा कि किसी ने आर्म मैप का उल्लेख नहीं किया है, मैं इसे व्यक्तिगत रूप से जोड़ूंगा क्योंकि मैंने C ++ वैज्ञानिक कार्यक्रम को प्रोफाइल करने के लिए सफलतापूर्वक मैप का उपयोग किया है।

आर्म MAP समानांतर, मल्टीथ्रेड या सिंगल थ्रेडेड C, C ++, फोरट्रान और F90 कोड के लिए प्रोफाइलर है। यह स्रोत लाइन के लिए गहराई से विश्लेषण और अड़चन प्रदान करता है। अधिकांश प्रोफाइलरों के विपरीत, यह समानांतर और थ्रेडेड कोड के लिए pthreads, OpenMP या MPI को प्रोफाइल करने में सक्षम होने के लिए डिज़ाइन किया गया है।

एमएपी वाणिज्यिक सॉफ्टवेयर है।


0

डिबगिंग सॉफ़्टवेयर का उपयोग करें कि कैसे पहचानें कि कोड धीरे-धीरे कहां चल रहा है?

जरा सोचिए जब आप गति में होते हैं तो आपको एक बाधा होती है तो यह आपकी गति को कम कर देगा

इस तरह अनचाहे रीएलोकेशन की लूपिंग, बफर ओवरफ्लो, सर्चिंग, मेमोरी लीकेज आदि ऑपरेशंस में ज्यादा एग्जीक्यूटिव पावर खर्च होती है, यह कोड के प्रदर्शन पर प्रतिकूल प्रभाव डालेगा, प्रोफाइलिंग से पहले कंपाइल करने के लिए ऐड-टू अवश्य करें:

g++ your_prg.cpp -pgया cc my_program.cpp -g -pgअपने संकलक के अनुसार

अभी तक यह कोशिश नहीं की है, लेकिन मैंने google-perftools के बारे में अच्छी बातें सुनी हैं। यह निश्चित रूप से एक कोशिश के काबिल है।

valgrind --tool=callgrind ./(Your binary)

यह gmon.out या callgrind.out.x नामक एक फ़ाइल उत्पन्न करेगा। फिर आप इस फ़ाइल को पढ़ने के लिए kcachegrind या डीबगर टूल का उपयोग कर सकते हैं। यह आपको परिणामों के साथ चीजों का एक ग्राफिकल विश्लेषण देगा जैसे कि कौन सी लाइनों की लागत कितनी है।

मुझे ऐसा लगता है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.