2011-05-28 19 views
9

हम एक बैंक में एक बड़ा वित्तीय आवेदन विकसित कर रहे हैं। यह वास्तव में खराब कोड की 150k लाइनों के रूप में शुरू हुआ। 1 महीने पहले, यह आधा से थोड़ा अधिक था, लेकिन निष्पादन योग्य का आकार अभी भी बड़ा था। मुझे उम्मीद थी कि चूंकि हम कोड को और अधिक पठनीय बना रहे थे, लेकिन टेम्पलेट कोड अभी भी बहुत सारे ऑब्जेक्ट कोड उत्पन्न कर रहा था, हम अपने प्रयास के साथ और अधिक कुशल थे।विशाल निष्पादन योग्य, क्यों?

एप्लिकेशन लगभग 5 साझा वस्तुओं और मुख्य में टूटा हुआ है। बड़ी साझा वस्तुओं में से एक 40 एमबी था और कोड कम होने के बावजूद 50 तक बढ़ गया।

मुझे पूरी तरह से आश्चर्य नहीं हुआ कि कोड बढ़ने लगा, क्योंकि आखिरकार हम कुछ कार्यक्षमता जोड़ रहे हैं। लेकिन मुझे आश्चर्य हुआ कि यह 20% तक बढ़ गया। निश्चित रूप से कोई भी 20% कोड लिखने के करीब नहीं आया, इसलिए मेरे लिए कल्पना करना मुश्किल है कि यह कितना बड़ा हुआ। यह मॉड्यूल मेरे लिए विश्लेषण करने के लिए कठिन है, लेकिन शुक्रवार को, मेरे पास एक नया डेटापॉइंट है जो कुछ प्रकाश डालता है।

एसओएपी सर्वरों के लिए शायद 10 फ़ीड्स हैं। कोड बुरी तरह से स्वत: उत्पन्न है।

#include <boost/shared_ptr.hpp> 
#include <xercesstuff...> 
class ParserService1 { 
public: 
    void parse() { 
    try { 
     Service1ContentHandler*p = new Service1ContentHandler(...); 
     parser->setContentHandler(p); 
     parser->parser(); 
    } catch (SAX ...) { 
     ... 
    } 
    } 
}; 

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

तो मैं पार्सर कक्षाओं और कोड से हटाए जाने पर कोड के आकार को नीचे जाने की उम्मीद कर रहा था। लेकिन केवल 10 सेवाओं के साथ, मैं 38 एमबी से 36 एमबी तक गिरने की उम्मीद नहीं कर रहा था। यह प्रतीकों की एक अपमानजनक मात्रा है।

एकमात्र चीज जिसे मैं सोच सकता हूं वह यह है कि प्रत्येक पार्सर में boost :: shared_ptr, कुछ Xerces पार्सर सामान शामिल थे, और किसी भी तरह, कंपाइलर और लिंकर प्रत्येक फ़ाइल के लिए बार-बार उन सभी प्रतीकों को संग्रहीत कर रहे हैं। मैं किसी भी मामले में पता लगाने के लिए उत्सुक हूँ।

तो, क्या कोई सुझाव दे सकता है कि मैं इस बारे में क्या सोचूंगा कि इस तरह के एक साधारण संशोधन का इतना प्रभाव क्यों होना चाहिए? मैं अंदरूनी प्रतीकों को देखने के लिए मॉड्यूल पर एनएम का उपयोग कर सकता हूं, लेकिन यह एक दर्दनाक, भारी मात्रा में अर्द्ध-पठनीय सामान उत्पन्न करने जा रहा है।

इसके अलावा, जब एक सहयोगी ने मेरी नई लाइब्रेरी के साथ अपना कोड चलाया, तो उपयोगकर्ता का समय 1m55 सेकेंड से 1m25 सेकेंड तक चला गया। वास्तविक समय अत्यधिक परिवर्तनीय है, क्योंकि हम धीमी एसओएपी सर्वरों पर इंतजार कर रहे हैं (आईएमएचओ, एसओएपी कॉरबा के लिए अविश्वसनीय रूप से खराब प्रतिस्थापन है ...) लेकिन सीपीयू का समय काफी स्थिर है। मुझे कोड आकार को कम करने से थोड़ा सा बढ़ावा मिलेगा, लेकिन नीचे की रेखा भारी मेमोरी वाले सर्वर पर है, मैं वास्तव में हैरान था कि गति इतनी प्रभावित हुई थी, क्योंकि मैंने आर्किटेक्चर को नहीं बदला एक्सएमएल प्रसंस्करण खुद।

मैं इसे मंगलवार को और अधिक लेने जा रहा हूं, और उम्मीद है कि अधिक जानकारी प्राप्त होगी, लेकिन अगर किसी को यह पता चल जाए कि मैं इसे कितना सुधार प्राप्त कर सकता हूं, तो मुझे जानना अच्छा लगेगा।

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

मेरे कोड लगता है:

#include "includetorture.h" 
void f1() 
{ 
    f2(); // call the function in the next file 
} 

आकार मेरी विशेष के साथ 100k के बारे में प्रति स्रोत फ़ाइल था फ़ाइलों में शामिल हैं। संभवतः, अगर मैंने और अधिक शामिल किया था, तो यह अधिक होगा। इसमें कुल निष्पादन योग्य ~ 600k था, लगभग 9 के बिना। मैंने सत्यापित किया कि विकास सहित फाइलों की संख्या के साथ रैखिक है, लेकिन पट्टी कोड समान आकार है, जैसा कि यह होना चाहिए।

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

+0

मैग्नस संपादित करने के लिए धन्यवाद! – Dov

+0

अपने शीर्षक में आप डिबगिंग प्रतीकों का उल्लेख करते हैं, लेकिन आप अपनी बाकी पोस्ट में नहीं हैं। क्या मैं कुछ भूल रहा हूँ? – Bart

+0

@ बार्ट ब्लॉउट एक्जिक्यूटिव में सभी डिबगिंग प्रतीकों की वजह से है। यदि आप पुस्तकालयों को पट्टी करते हैं, तो कोड आकार का लगभग 10% है। – Dov

उत्तर

5

आप exe फ़ाइल में विभिन्न प्रकार के डेटा द्वारा उपयोग की जाने वाली जगह की सटीक मात्रा को खोजने के लिए लिनक्स, या डंपबिन पर रीडल्फ यूटिलिटी का उपयोग कर सकते हैं। हालांकि, मुझे नहीं पता कि निष्पादन योग्य आकार आपको चिंता क्यों कर रहा है: डिबगिंग प्रतीकों का उपयोग बिल्कुल समय पर कोई स्मृति नहीं है!

+1

स्पष्ट रूप से, केवल उस मात्रा की मात्रा उत्पन्न करने में समय लगता है। मैं इस प्रवृत्ति के बारे में चिंतित हूं। यहां थे, कोड आकार को कम करना, और फिर भी निष्पादन योग्य 20% तक फूला हुआ। हालांकि यह जानना अच्छा है कि वे रनटाइम पर लोड नहीं होते हैं .... – Dov

+1

सी ++ प्रतीक बहुत लंबे समय तक बन जाते हैं क्योंकि नाम उलझन में होता है; बूस्ट का उपयोग करते समय यह विशेष रूप से स्पष्ट है। एक प्रतीत होता है "सरल" प्रकार, जैसे कुछ बढ़ावा टेम्पलेट के तत्कालता, उलझन वाले नाम उत्पन्न कर सकते हैं जो कि कुछ केबी लंबाई में हैं! ऐसे मामलों में, डिबगिंग जानकारी का आकार विभिन्न इकाइयों (विधियों, कार्यों, तत्काल टेम्पलेट्स) के NUMBER द्वारा नियंत्रित होता है। यह एक ज्ञात समस्या है, और कुछ बूस्ट लाइब्रेरीज़ अपने मैनुअल में प्रतीक नाम की लंबाई को कम करने का पता लगाते हैं। लेकिन, फिर, आप कोड आकार को कम करने की कोशिश क्यों कर रहे हैं? – zvrba

+1

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

2

ऐसा लगता है कि आप इनलाइन विधियों के साथ बहुत से सी ++ कक्षाओं का उपयोग कर रहे हैं। यदि इन वर्गों में उच्च दृश्यता है, तो यह इनलाइन कोड पूरे एप्लिकेशन को फहराएगा। मैं शर्त लगाता हूं कि आपके लिंक के समय भी बढ़ गए हैं। इनलाइन विधियों की संख्या को कम करने का प्रयास करें और कोड को .cpp फ़ाइलों में ले जाएं। यह आपकी ऑब्जेक्ट फ़ाइलों के आकार को कम करेगा, exe फ़ाइल और लिंक समय को कम करेगा।

इस मामले में व्यापार बंद निश्चित रूप से संकलन इकाइयों के आकार को कम कर देता है, बनाम निष्पादन समय।

+0

यदि यह xerces और boost है, तो मुझे यकीन नहीं है कि मैं उनकी सामग्री संपादित करना चाहता हूं, लेकिन मैं एक नज़र डालेगा। – Dov

+0

यदि कोड रेखांकित है, और नहीं कहा जाता है, तो कोई प्रभाव नहीं होना चाहिए। मुझे संदेह है कि यह वैश्विक चर के कारण है, और उन सभी प्रतीकों में खींच रहा है जिन्हें वे संदर्भित करते हैं। लेकिन मुझे नहीं पता कि लिंकर निष्पादन योग्य में कई प्रतियां क्यों रखता है - शायद उनसे छुटकारा पाने के लिए बहुत महंगा है। – Dov

+0

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

2

मेरे पास आपके प्रश्न की अपेक्षा करने वाला बहुत ही उत्तर नहीं है, लेकिन मुझे अपना अनुभव साझा करने दें।

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

आकार में अंतर इतना बड़ा है कि यदि आप कहते हैं, कुछ साझा पुस्तकालयों को गतिशील रूप से लोड करना, तो फ़ाइल के निचले लोडिंग समय को आपके द्वारा प्राप्त प्रदर्शन में अंतर समझा सकता है।

दरअसल, यह कंपाइलरों का एक सुंदर "आंतरिक" पहलू है, और सिर्फ आपको एक उदाहरण देने के लिए, साल पहले मैं बड़ी निष्पादन योग्य फाइलों से काफी नाखुश था, जीसीसी -4 की तुलना में जीसीसी -4 उत्पादित, तो मैं बस इसका इस्तेमाल किया गया (और मेरा एचडी आकार में भी बढ़ गया)।

सब कुछ, मुझे कोई फर्क नहीं पड़ता, क्योंकि आप केवल विकास के दौरान डिबगिंग प्रतीकों के साथ निर्माण का उपयोग करना चाहते हैं, जहां यह कोई मुद्दा नहीं होना चाहिए। तैनाती में, कोई डिबगिंग प्रतीक बस वहां नहीं है, और आप देखेंगे कि फाइलें कितनी कम हो जाएंगी।

+0

सेर्गियो से उम्मीद करते हैं, परीक्षण के बाद यह सच नहीं होता है। निष्पादन योग्य आकार में गति के साथ कुछ भी नहीं है, कम से कम छोटे परीक्षण में मैंने किया था। और यह यादृच्छिक नहीं था, मैं एक प्रयोग कर सकता हूं, और अप्रिय, अगर यह अप्रिय है। – Dov

+0

@Dov, इसे जांचने के लिए धन्यवाद। असल में मेरा मतलब था * लोडिंग समय *। यदि आपके पास कई साझा पुस्तकालय हैं, प्रत्येक 10 एमबी आकार और प्रतीकों से भरा है, और आप उन्हें गतिशील रूप से लोड करते हैं, तो जब आप उन्हें लोड करते हैं, तो गतिशील लिंकिंग के कारण आपका प्रोग्राम धीमा हो जाएगा। यदि आप दस मंदी की गिनती करते हैं, तो आप कुछ ध्यान देने योग्य हो सकते हैं। लेकिन यह सिर्फ एक विचार था, क्योंकि मुझे नहीं पता कि आपका एप्लिकेशन किस प्रकार आर्किटेक्टेड है। वैसे भी, चूंकि आपने निष्पादन योग्य को हटा दिया है, इसलिए मैं समझता हूं कि लोडिंग समय आपके ऐप को भी प्रभावित नहीं कर रहा था। – sergio

+0

मेरा परीक्षण निश्चित रूप से बहुत छोटी फाइलों पर था, लेकिन हम 10 मिनट के रन टाइम के साथ एक बड़ी नौकरी के बारे में बात कर रहे हैं, इसलिए यदि यह कुछ सेकंड के लिए लोड हो गया है, तो 100 एमबी का प्रभाव बहुत अधिक नहीं होना चाहिए था वास्तव में, यह नहीं था। – Dov

संबंधित मुद्दे