14

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

मेरी समस्या यह है कि विघटनकर्ता केवल अंगूठी बफर में एक प्रकार की वस्तु स्वीकार करता है। यह समझ में आता है क्योंकि विघटनकर्ता अंगूठी बफर में वस्तुओं को पूर्व-आवंटित करता है। हालांकि, यह विघटनकर्ता के माध्यम से मेरे व्यापार तर्क धागे में दो अलग-अलग प्रकार के संदेशों को पार करना मुश्किल बनाता है।

  1. कॉन्फ़िगर disruptor एक तय आकार बाइट सरणी (के रूप में How should one use Disruptor (Disruptor Pattern) to build real-world message systems? द्वारा सिफारिश की) युक्त वस्तुओं का उपयोग करने के: से मैं क्या बता सकते हैं, मैं चार विकल्प हैं। इस मामले में, मुख्य थ्रेड को विघटनकर्ता को प्रकाशित करने से पहले संदेशों को बाइट एरे में एन्कोड करना होगा और प्रत्येक व्यवसाय तर्क धागे को बाइट एरे को रसीद पर वस्तुओं में वापस डीकोड करना होगा। इस सेटअप का नकारात्मक पक्ष यह है कि व्यापार तर्क धागे वास्तव में विघटनकर्ता से स्मृति साझा नहीं कर रहे हैं - इसके बजाय वे विघटनकर्ता द्वारा प्रदान किए गए बाइट सरणी से नई वस्तुओं (और इस प्रकार कचरा बना रहे हैं) बना रहे हैं। इस सेटअप का उछाल यह है कि सभी व्यावसायिक तर्क धागे एक ही विघटनकर्ता से कई अलग-अलग प्रकार के संदेशों को पढ़ सकते हैं।

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

  3. "सुपर" वस्तु कि दोनों संदेश एक के सभी क्षेत्रों में शामिल है और बी यह बहुत OO शैली के खिलाफ है एक प्रकार का उपयोग करने के लिए disruptor कॉन्फ़िगर है, लेकिन # 1 विकल्प और # के बीच एक समझौता के लिए अनुमति देगा 2।

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

इस स्थिति के लिए आप क्या सलाह देते हैं? मुझे लगता है कि विकल्प # 2 सबसे साफ समाधान है, लेकिन मुझे नहीं पता कि उपभोक्ता तकनीकी रूप से कई विघटनकर्ताओं के संदेशों की सदस्यता कैसे ले सकते हैं या नहीं। यदि कोई विकल्प # 2 को कार्यान्वित करने के लिए एक उदाहरण प्रदान कर सकता है, तो इसकी सराहना की जाएगी!

+5

माइकल बार्कर Disruptor Google समूह में मेरे प्रश्न का उत्तर प्रकाशित करते हैं। नीचे उसकी प्रतिक्रिया देखें: https://groups.google.com/d/msg/lmax-disruptor/clUkJaFMsZg/54fKplz21MwJ –

+4

यदि यह आपके प्रश्न का उत्तर देता है तो इसे यहां एक उत्तर में परिवर्तित करने पर विचार करें और उस उत्तर को स्वीकृत के रूप में चिह्नित करें। – cic

उत्तर

2

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

यह मेरी प्राथमिकता दी दृष्टिकोण होगा, लेकिन मैं थोड़ा, बस हर जगह है कि हम Disruptor यह या तो से प्राप्त करने या आई/ओ डिवाइस के कुछ प्रकार के लिए भेजने से है का उपयोग किया है के बारे में हमारी उपयोग के मामलों द्वारा रंग, इसलिए हमारे मूल मुद्रा बाइट सरणी है। आप मार्शलिंग के लिए फ्लाईवेट दृष्टिकोण का उपयोग कर ऑब्जेक्ट सृजन के आस-पास प्राप्त कर सकते हैं। का उदाहरण देखने के लिए, मैंने उदाहरण के लिए जैवोल्यूशन स्ट्रक्चर एंड यूनियन क्लासेस का उपयोग किया जो मैंने देवॉक्सक्स (https://github.com/mikeb01/ticketing) में प्रस्तुत किया था। यदि आप ईवेंट हैंडलर से ऑनवेन्ट कॉल से लौटने से पहले ऑब्जेक्ट से पूरी तरह से निपट सकते हैं तो यह दृष्टिकोण अच्छी तरह से काम करता है। यदि ईवेंट को उस बिंदु से परे रहने की आवश्यकता है तो आपको डेटा की प्रतिलिपि बनाने के लिए कुछ प्रकार बनाना होगा, उदा। इसे एक वस्तु में de-serialising।

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

इस दृष्टिकोण की कोशिश नहीं की गई, आपको शायद एक कस्टम इवेंटप्रोसेसर की आवश्यकता होगी जो एकाधिक रिंग बफर से मतदान कर सकता है।

"सुपर" उद्देश्य यह है कि दोनों संदेश एक के सभी क्षेत्रों में शामिल है और बी यह बहुत OO शैली के खिलाफ है एक प्रकार का उपयोग करने के लिए disruptor कॉन्फ़िगर, लेकिन # 1 विकल्प और के बीच एक समझौता के लिए अनुमति देगा # 2। ऑब्जेक्ट संदर्भों का उपयोग करने के लिए विघटनकर्ता को कॉन्फ़िगर करें। हालांकि, इस मामले में मैं ऑब्जेक्ट प्रीलोकेशन और मेमोरी ऑर्डरिंग के प्रदर्शन लाभ खो देता हूं।

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

इस स्थिति के लिए आप क्या सलाह देते हैं?मुझे लगता है कि विकल्प # 2 स्वच्छतम समाधान है, लेकिन मुझे नहीं पता कि उपभोक्ता तकनीकी रूप से एकाधिक विघटनकर्ताओं के संदेशों की सदस्यता ले सकते हैं या नहीं। यदि कोई विकल्प # 2 को कार्यान्वित करने के लिए उदाहरण प्रदान कर सकता है, तो इसकी बहुत सराहना की जाएगी!

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

1

बेन बाउमगोल्ड, मुझे यकीन है कि अब तक आपको एक समाधान मिला है। एक ईवेंट धारक बनाकर आपका # 4 (या # 3) छोटा रूप से कार्यान्वित किया जा सकता है। वस्तुओं के लिए enum के रूप में इसके बारे में सोचो। लुक-अप की गति के लिए, घटनाओं को एक enum प्रकार के साथ समृद्ध किया जाना चाहिए। ध्यान दें, मैं धारक में मूल घटना का संदर्भ संग्रहीत कर रहा हूं। प्रतिलिपि बनाने वाले या क्लोन() को बनाने के लिए और अधिक उचित हो सकता है और रिंग बफर में सम्मिलन पर ईवेंट कॉपी करें।

उदाहरण के द्वारा दृष्टांत:

// इस घटनाओं

public enum MyEventEnum { 
EVENT_TIMER, 
EVENT_MARKETDATA; 
} 

// इस धारक है में प्रयोग किया जाता enum है। किसी भी समय, रिंगबफर में यह उदाहरण सरणी [type.ordinal()] द्वारा अनुक्रमित केवल एक ईवेंट रखता है। कोड से सरणी स्पष्ट क्यों होनी चाहिए।

public class RingBufferEventHolder {  
private MyEventEnum; 
private EventBase array[]; 

public RingBufferEventHolder() { 
    array=new EventBase[MyEventEnum.values().length]; 
} 

// TODO: null the rest 
public void setEvent(EventBase event) { 
    type=event.getType(); 
    switch(event.getType()) { 
     case EVENT_TIMER: 
      array[MyEventEnum.EVENT_TIMER.ordinal()]=event; 
      break; 
     case EVENT_MARKETDATA: 
      array[MyEventEnum.EVENT_MARKETDATA.ordinal()]=event; 
      break; 
     default: 
      throw new RuntimeException("Unknown event type " + event); 
    } 
} 

// घटना

EventBase newEvent=new EventMarketData(....); 
    // prepare 
    long nextSequence = ringBuffer.next(); 
    RingBufferEventHolder holder = ringBuffer.get(nextSequence); 
    holder.setEvent(newEvent); 
    // make the event available to EventProcessors 
    ringBuffer.publish(nextSequence); 
संबंधित मुद्दे