प्रॉम्प्ट और दायरा
एक टीम पारंपरिक for range b.N बेंचमार्क के साथ दो पार्सर की तुलना करती है। सेटअप और क्लीनअप कभी-कभी टाइमिंग में शामिल हो जाते हैं, और कंपाइलर उन परिणामों को हटा सकता है जिन्हें कभी देखा नहीं जाता है। एक दोहराने योग्य (repeatable) बेंचमार्क डिज़ाइन करने के लिए Go 1.24 testing.B.Loop का उपयोग करें, और बताएं कि यह वास्तविक वर्कलोड, एलोकेशन विश्लेषण या क्रॉस-मशीन तुलना की जगह क्यों नहीं लेता है।
यह बैकएंड कोडिंग, परफॉर्मेंस इंजीनियरिंग और इंफ्रास्ट्रक्चर भूमिकाओं के लिए उपयुक्त है। मुख्य कौशल बेंचमार्क डिज़ाइन है, इसलिए यह coding के अंतर्गत आता है। इस राउंड में कोडिंग लगातार है क्योंकि फ्रंटएंड, प्रोडक्ट और व्यावहारिक (behavioral) उम्मीदवारों के प्रश्न मौजूदा प्रश्नों के साथ ओवरलैप हो रहे थे, जबकि B.Loop के पास नए आधिकारिक API साक्ष्य हैं।
इंटरव्यूअर्स क्या आकलन करते हैं
पहला, क्या आप जानते हैं कि b.Loop मापे गए इटरेशन से सेटअप और क्लीनअप को बाहर रखता है और मैन्युअल टाइमर-कंट्रोल की गलतियों को कम करता है?
दूसरा, क्या आप कंपाइलर सुरक्षा को समझते हैं? लूप की स्थिति कंपाइलर को बेंचमार्क लूप को पहचानने में मदद करती है और भ्रामक डेड-कोड एलिमिनेशन को कम करती है।
तीसरा, क्या आप कुल-इटरेशन निर्भरता से बच सकते हैं? एक बेंचमार्क को प्रति इटरेशन काम करना चाहिए; b.N को बिज़नेस बैच साइज़ या स्टेट ID नहीं बनना चाहिए।
चौथा, क्या आप म्यूटेबल स्टेट, एलोकेशन, कैश और पैरेललिज्म को संभाल सकते हैं? प्रति इटरेशन स्टेट को रीसेट या अलग (isolate) करें, फिर ReportAllocs, प्रोफाइल और प्रोडक्शन संदर्भ के साथ परिणामों की व्याख्या करें।
पांचवां, क्या आप वितरण (distributions) की तुलना कर सकते हैं? एक अकेला ns/op रन सामान्य लाभ साबित नहीं करता है; स्थितियों को स्थिर (pin) करें और शोर (noise) देखने के लिए पर्याप्त दोहराएं।
पहले स्पष्ट करने योग्य प्रश्न
- क्या लक्षित Go संस्करण कम से कम 1.24 है?
- क्या हम थ्रूपुट, लेटेंसी, एलोकेशन, या टेल लेटेंसी को माप रहे हैं?
- क्या इनपुट का पुन: उपयोग किया जा सकता है, और क्या पार्सर बफर को म्यूटेट करता है?
- क्या हमें
-benchmem, CPU प्रोफाइल, या पैरेलल बेंचमार्क की आवश्यकता है? - क्या CPU फ्रीक्वेंसी, कंटेनर कोटा और कैश स्थिति नियंत्रित हैं?
- क्या परिणाम इटरेशन काउंट या रैंडम सीड पर निर्भर करता है?
30-सेकंड उत्तर फ्रेमवर्क
"मैं केवल परीक्षण के तहत ऑपरेशन को for b.Loop() के अंदर रखूंगा, महंगे फिक्सचर सेटअप और अंतिम क्लीनअप को बाहर रखूंगा, प्रति इटरेशन इनपुट को रीसेट करूंगा, और कम लागत वाले सिंक (sink) या असर्शन के माध्यम से परिणामों को देखूंगा। मैं Go, CPU और कैश स्थितियों को स्थिर रखूंगा, -benchmem, प्रोफाइल और बार-बार काउंट चलाऊंगा, और वितरण की तुलना करूंगा। विभिन्न मशीनों से एक एकल ns/op प्रोडक्शन निष्कर्ष नहीं है।"
चरण-दर-चरण उत्तर
चरण 1: संस्करण और कमांड स्थिर करें
testing.B.Loop Go 1.24 में आया है। स्थानीय स्तर पर और CI में समान टूलचेन का उपयोग करें, और go version, बिल्ड टैग, -benchtime, -count, -cpu, और बेंचमार्क फिल्टर रिकॉर्ड करें ताकि प्रयोग तुलनीय हों।
चरण 2: टाइमिंग सीमा परिभाषित करें
लूप के बाहर फिक्सचर बनाएं, फाइलें लोड करें और वन-टाइम कनेक्शन स्थापित करें। यदि प्रत्येक इटरेशन को रीसेट की आवश्यकता है, तो केवल आवश्यक स्थिति को रीसेट करें; रैंडम डेटा निर्माण या क्लीनअप को तब तक न मापें जब तक कि वह वर्कलोड न हो।
func BenchmarkParse(b *testing.B) {
input := []byte(loadFixture())
b.ReportAllocs()
for b.Loop() {
data := append([]byte(nil), input...)
_ = parse(data)
}
}चरण 3: परिणाम एलिमिनेशन को रोकें
कंपाइलर उस काम को हटा सकता है जो अवलोकनीय (observable) स्थिति को प्रभावित नहीं कर सकता है। परिणामों को पैकेज-स्तरीय सिंक में लिखें, एक जांची गई वेरिएबल में संचित करें, या सिमेंटिक्स का दावा (assert) करें। सिंक को असंबद्ध लॉक या एलोकेशन नहीं जोड़ना चाहिए जो माप को विकृत करते हैं।
चरण 4: स्थिति और इटरेशन निर्भरता को संभालें
testing पैकेज लक्ष्य अवधि के आधार पर लूप काउंट चुनता है। इसे इनपुट साइज़ के रूप में न मानें। प्रति इटरेशन मैप, बफर, कैश और ग्लोबल स्टेट को साफ़ करें; वार्म और कोल्ड कैश के लिए अलग-अलग बेंचमार्क का उपयोग करें।
चरण 5: एलोकेशन और पैरेललिज्म का निरीक्षण करें
एलोकेशन काउंट और बाइट्स का निरीक्षण करने के लिए b.ReportAllocs() और -benchmem का उपयोग करें। RunParallel समवर्ती (concurrent) थ्रूपुट को मापता है, लेकिन शेयर्ड इनपुट, लॉक और GOMAXPROCS को प्रोडक्शन प्रश्न से मेल खाना चाहिए; एक सिंगल-गोरुटीन लेटेंसी बेंचमार्क भी रखें।
चरण 6: पर्यावरणीय शोर को नियंत्रित करें
CPU कोटा, फ्रीक्वेंसी पॉलिसी, कंटेनर सीमाएं और डेटासेट को स्थिर करें। -count के साथ चलाएं और माध्यिका (median) और प्रसार (spread) की रिपोर्ट करें; सबसे छोटे रन का चयन करने के बजाय benchstat जैसी सांख्यिकीय तुलना का उपयोग करें।
चरण 7: वास्तविक सत्यापन से जुड़ें
एक बेंचमार्क माइक्रो-पाथ को कवर करता है। यूजर पाथ का परीक्षण करने के लिए रिक्वेस्ट रीप्ले, लोड टेस्ट, CPU और मेमोरी प्रोफाइल, और प्रोडक्शन मेट्रिक्स का उपयोग करें। यदि माइक्रो लाभ एंड-टू-एंड p95 को प्रभावित नहीं करते हैं, तो ऑप्टिमाइज़ेशन शिप करने से पहले I/O या शेड्यूलिंग की जांच करें।
मॉडल उत्तर
"मैं Go 1.24 और बेंचमार्क मापदंडों को स्थिर करूंगा। फिक्सचर सेटअप for b.Loop() के बाहर रहता है; लूप में पार्सिंग और केवल आवश्यक इनपुट कॉपी शामिल होती है, जिसमें एक सस्ता सिंक होता है जो डेड-कोड एलिमिनेशन को रोकता है। म्यूटेबल बफर प्रति इटरेशन रीसेट होते हैं, और कोई भी परिणाम कुल लूप काउंट पर निर्भर नहीं करता है।
मैं एलोकेशन और शोर का निरीक्षण करने के लिए -benchmem, बार-बार -count, और प्रोफाइल का उपयोग करूंगा, और थ्रूपुट के लिए एक अलग RunParallel बेंचमार्क लिखूंगा। अंत में मैं वास्तविक अनुरोधों को रीप्ले करूंगा और एंड-टू-एंड p95 की तुलना करूंगा; एक एकल-मशीन ns/op परिणाम कोई प्रोडक्शन दावा नहीं है।"
सामान्य गलतियां
- लूप के अंदर सेटअप रखना → मापी गई वस्तु दूषित होती है → फिक्सचर को बाहर निकालें।
- परिणाम को कभी न देखना → कंपाइलर काम को हटा देता है → कम लागत वाले सिंक या असर्शन का उपयोग करें।
- b.N को व्यावसायिक इनपुट के रूप में उपयोग करना → बेंचमार्क अवधि के साथ परिणाम बदलते हैं → इटरेशन को स्वतंत्र बनाएं।
- एक बार चलाना → शोर लाभ जैसा दिखता है → दोहराएं और वितरण की तुलना करें।
- RunParallel को लेटेंसी परीक्षण के रूप में उपयोग करना → लॉक विवाद एकल-अनुरोध लागत को छुपाता है → थ्रूपुट और लेटेंसी को अलग करें।
- एलोकेशन आंकड़ों की अनदेखी करना → ns/op में सुधार होता है जबकि GC खराब होता है →
-benchmemऔर प्रोफाइल को मिलाएं। - विभिन्न मशीनों की सीधे तुलना करना → फ्रीक्वेंसी और कोटा भिन्न होते हैं → स्थितियों को नियंत्रित करें या आंकड़ों का उपयोग करें।
- केवल माइक्रोबेंचमार्क देखना → वास्तविक बाधा I/O हो सकती है → रीप्ले और एंड-टू-एंड परीक्षण चलाएं।
फॉलो-अप प्रश्न
फॉलो-अप 1: B.Loop और b.N के बीच मुख्य अंतर क्या है?
B.Loop इटरेशन और टाइमिंग सीमाओं का प्रबंधन करता है और मैन्युअल टाइमर और कंपाइलर-ऑप्टिमाइज़ेशन के जाल को कम करता है। कोड को कुल इटरेशन काउंट पर निर्भर नहीं होना चाहिए।
फॉलो-अप 2: आप अभी भी ResetTimer को कब कॉल करेंगे?
अधिकांश सेटअप और क्लीनअप को लूप के बाहर ले जाया जाना चाहिए। स्पष्ट टाइमर नियंत्रण फ़ंक्शन के अंदर के एक विशेष चरण के लिए है जिसे बाहर रखा जाना चाहिए; कारण का दस्तावेजीकरण करें।
फॉलो-अप 3: आप कैश हिट को कैसे मापते हैं?
स्पष्ट वार्मअप के साथ अलग-अलग वार्म-कैश और कोल्ड-कैश बेंचमार्क का उपयोग करें; एक लूप में स्थितियों को कभी न मिलाएं।
फॉलो-अप 4: क्या सिंक परिणाम बदल सकता है?
यह बदल सकता है। एक सरल, लॉक-मुक्त (lock-free), कम-एलोकेशन अवलोकन चुनें और इसकी लागत को प्रोफाइल करें; शुद्धता परीक्षणों को परफॉर्मेंस माप से अलग रखें।
फॉलो-अप 5: आप समवर्ती पार्सिंग का बेंचमार्क कैसे करते हैं?
एकल-गोरुटीन लेटेंसी बेंचमार्क बनाए रखते हुए, अलग इनपुट, निश्चित GOMAXPROCS, और थ्रूपुट, एलोकेशन और लॉक मेट्रिक्स के साथ RunParallel का उपयोग करें।
फॉलो-अप 6: आपको माइक्रो-ऑप्टिमाइज़िंग कब बंद कर देनी चाहिए?
जब एंड-टू-एंड मेट्रिक्स में सुधार न हो, लाभ शोर से कम हो, या I/O, नेटवर्क या शेड्यूलिंग हावी हो, तब रुकें। पूर्ण अनुरोध पथ पर वापस आएं।