गो के साथ एक निजी परियोजना में, जो बोवेस्पा से वित्तीय संपत्तियों के बारे में जानकारी प्राप्त करता है।
सिस्टम गोरआउट्स के साथ समवर्तीता और समानता का गहन उपयोग करता है, हर 8 सेकंड में संपत्ति की जानकारी (व्यावसायिक गणना के साथ) अपडेट करता है।
प्रारंभ में, कोई त्रुटि या चेतावनी दिखाई नहीं दी, लेकिन मैंने देखा कि कुछ गोरोइन को निष्पादित होने में दूसरों की तुलना में अधिक समय लग रहा था।
अधिक विशिष्ट होने के लिए, जबकि पी99 समय 0.03 एमएस था, कुछ बिंदुओं पर, यह बढ़कर 0.9 एमएस हो गया। इसने मुझे समस्या की और जांच करने के लिए प्रेरित किया।
मुझे पता चला कि मैं एक सेमाफोर गोरोइन पूल का उपयोग कर रहा था, जो GOMAXPROCS वेरिएबल के आधार पर बनाया गया था।
हालाँकि, मुझे एहसास हुआ कि इस दृष्टिकोण में एक समस्या थी।
जब हम GOMAXPROCS वेरिएबल का उपयोग करते हैं, तो यह कंटेनर में उपलब्ध कोर की संख्या को सही ढंग से कैप्चर नहीं करता है। यदि कंटेनर में वीएम के कुल से कम उपलब्ध कोर हैं, तो यह वीएम के कुल पर विचार करता है। उदाहरण के लिए, मेरे वीएम में 8 कोर उपलब्ध हैं, लेकिन कंटेनर में केवल 4 थे। इसके परिणामस्वरूप एक ही समय में चलने के लिए 8 गोरोइन बनाए गए, जिससे थ्रॉटलिंग हुई।
रात भर बहुत शोध करने के बाद, मुझे उबर द्वारा विकसित एक लाइब्रेरी मिली जो स्वचालित रूप से GOMAXPROCS वैरिएबल को अधिक कुशलता से समायोजित करती है, भले ही वह कंटेनर में हो या नहीं। यह समाधान बेहद स्थिर और कुशल साबित हुआ: ऑटोमैक्सप्रोक्स
लिनक्स कंटेनर सीपीयू कोटा से मिलान करने के लिए GOMAXPROCS को स्वचालित रूप से सेट करें।
go get -u go.uber.org/automaxprocs
import _ "go.uber.org/automaxprocs"
func main() {
// Your application logic here.
}
उबेर के आंतरिक लोड बैलेंसर से मापा गया डेटा। हमने लोड बैलेंसर को 200% सीपीयू कोटा (यानी, 2 कोर) के साथ चलाया:
GOMAXPROCS | आरपीएस | P50 (एमएस) | P99.9 (एमएस) |
---|---|---|---|
1 | 28,893.18 | 1.46 | 19.70 |
2 (कोटा के बराबर) | 44,715.07 | 0.84 | 26.38 |
3 | 44,212.93 | 0.66 | 30.07 |
4 | 41,071.15 | 0.57 | 42.94 |
8 | 33,111.69 | 0.43 | 64.32 |
डिफ़ॉल्ट (24) | 22,191.40 | 0.45 | 76.19 |
जब GOMAXPROCS को CPU कोटा से ऊपर बढ़ाया जाता है, तो हम P50 को थोड़ा कम होते देखते हैं, लेकिन P99 तक महत्वपूर्ण वृद्धि देखते हैं। हम यह भी देखते हैं कि संभाले गए कुल आरपीएस में भी कमी आती है।
जब GOMAXPROCS आवंटित सीपीयू कोटा से अधिक है, तो हमने महत्वपूर्ण थ्रॉटलिंग भी देखी:
$ cat /sys/fs/cgroup/cpu,cpuacct/system.slice/[...]/cpu.stat nr_periods 42227334 nr_throttled 131923 throttled_time 88613212216618
एक बार जब GOMAXPROCS को सीपीयू कोटा से मिलान करने के लिए कम कर दिया गया, तो हमने कोई सीपीयू थ्रॉटलिंग नहीं देखी।
इस लाइब्रेरी के उपयोग को लागू करने के बाद, समस्या हल हो गई, और अब पी99 समय लगातार 0.02 एमएस पर बना हुआ है। इस अनुभव ने समवर्ती प्रणालियों में अवलोकन और प्रोफाइलिंग के महत्व पर प्रकाश डाला।
निम्नलिखित एक बहुत ही सरल उदाहरण है, लेकिन प्रदर्शन में अंतर प्रदर्शित करता है।
गो के मूल परीक्षण और बेनकमैक पैकेज का उपयोग करके, मैंने दो फ़ाइलें बनाईं:
benchmarking_with_enhancement_test.go:
package main import ( _ "go.uber.org/automaxprocs" "runtime" "sync" "testing" ) // BenchmarkWithEnhancement Função com melhoria, para adicionar o indice do loop em um array de inteiro func BenchmarkWithEnhancement(b *testing.B) { // Obtém o número de CPUs disponíveis numCPUs := runtime.NumCPU() // Define o máximo de CPUs para serem usadas pelo programa maxGoroutines := runtime.GOMAXPROCS(numCPUs) // Criação do semáforo semaphore := make(chan struct{}, maxGoroutines) var ( // Espera para grupo de goroutines finalizar wg sync.WaitGroup // Propriade mu sync.Mutex // Lista para armazenar inteiros list []int ) // Loop com mihão de indices for i := 0; ibenchmarking_without_enhancement_test.go:
package main import ( "runtime" "sync" "testing" ) // BenchmarkWithoutEnhancement Função sem a melhoria, para adicionar o indice do loop em um array de inteiro func BenchmarkWithoutEnhancement(b *testing.B) { // Obtém o número de CPUs disponíveis numCPUs := runtime.NumCPU() // Define o máximo de CPUs para serem usadas pelo programa maxGoroutines := runtime.GOMAXPROCS(numCPUs) // Criação do semáforo semaphore := make(chan struct{}, maxGoroutines) var ( // Espera para grupo de goroutines finalizar wg sync.WaitGroup // Propriade mu sync.Mutex // Lista para armazenar inteiros list []int ) // Loop com mihão de indices for i := 0; iउनके बीच अंतर यह है कि कोई उबर लाइब्रेरी आयात का उपयोग करता है।
यह मानते हुए बेंचमार्क चलाते समय कि 2 सीपीयू का उपयोग किया जाएगा, परिणाम यह था:
ns/op: किसी विशिष्ट ऑपरेशन को करने में कितना समय लगता है इसका नैनोसेकंड में औसत प्रदान करता है।
ध्यान दें कि मेरे सीपीयू की कुल उपलब्धता 8 कोर है, और रनटाइम.NumCPU() संपत्ति यही लौटाती है। हालाँकि, जैसा कि बेंचमार्क चलाने में, मैंने परिभाषित किया कि उपयोग केवल दो सीपीयू होगा, और फ़ाइल जो ऑटोमैक्सप्रोक्स का उपयोग नहीं करती है, परिभाषित करती है कि एक समय में निष्पादन सीमा 8 गोरोइन होगी, जबकि सबसे कुशल 2 होगी, क्योंकि इस तरह कम आवंटन का उपयोग करने से निष्पादन अधिक कुशल हो जाता है।
इसलिए, हमारे अनुप्रयोगों की अवलोकनशीलता और प्रोफाइलिंग का महत्व स्पष्ट है।
अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।
Copyright© 2022 湘ICP备2022001581号-3