जावा और C / C ++ के बीच इंटर प्रोसेस कम्युनिकेशन के लिए सबसे तेज़ (कम विलंबता) विधि


100

मेरे पास एक जावा ऐप है, जो टीसीपी सॉकेट के माध्यम से सी / सी ++ में विकसित एक "सर्वर" से जुड़ रहा है।

ऐप और सर्वर दोनों एक ही मशीन पर चल रहे हैं, एक सोलारिस बॉक्स (लेकिन हम अंततः लिनक्स में माइग्रेट करने पर विचार कर रहे हैं)। एक्सचेंज किए गए डेटा का प्रकार सरल संदेश है (लॉगिन, लॉगिन एसीके, फिर क्लाइंट कुछ मांगता है, सर्वर जवाब देता है)। प्रत्येक संदेश लगभग 300 बाइट लंबा है।

वर्तमान में हम सॉकेट्स का उपयोग कर रहे हैं, और सभी ठीक है, हालांकि मैं IPC विधियों का उपयोग करके डेटा (कम विलंबता) का आदान-प्रदान करने का तेज़ तरीका ढूंढ रहा हूं।

मैं नेट पर शोध कर रहा हूं और निम्नलिखित तकनीकों के संदर्भ में आया हूं:

  • शेयर्ड मेमोरी
  • पाइप
  • कतारों
  • साथ ही डीएमए (डायरेक्ट मेमोरी एक्सेस) के रूप में क्या संदर्भित है

लेकिन मैं उनके संबंधित प्रदर्शनों का समुचित विश्लेषण नहीं कर पाया, न ही उन्हें JAVA और C / C ++ (ताकि वे एक-दूसरे से बात कर सकें) दोनों में लागू किया जा सके, सिवाय शायद पाइप के कि मैं कैसे कल्पना कर सकता हूं।

क्या इस संदर्भ में प्रत्येक विधि के प्रदर्शन और व्यवहार्यता के बारे में कोई टिप्पणी कर सकता है? किसी भी सूचक / उपयोगी कार्यान्वयन जानकारी के लिए लिंक?


संपादित करें / अद्यतन करें

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

अगले संभव कदम पाइप का प्रत्यक्ष कार्यान्वयन होगा, फिर साझा की गई मेमोरी, हालांकि मुझे जटिलता के अतिरिक्त स्तर की चेतावनी दी गई है ...


आपकी सहायता के लिए धन्यवाद


7
यह आपके मामले में ओवरकिल हो सकता है लेकिन zeromq.org
jfs

यह दिलचस्प है, हालांकि यह विचार "जेनेरिक" (जैसे ओएस-प्रदान या भाषा-प्रदान की गई) विधियों का उपयोग करना होगा, यही कारण है कि मैंने कतारों और साझा मेमोरी का उल्लेख किया है।
बस्तियन

2
यह भी देखें stackoverflow.com/questions/904492
MSalters

मैप की गई फ़ाइलों या यूडीपी को न भूलें।

10
UDP धीमी टीसीपी से ???
हम्म

जवाबों:


103

मेरे Corei5 2.8GHz पर जावा से बस परीक्षण किए गए विलंबता, केवल एकल बाइट भेजें / प्राप्त करें, 2 जावा प्रक्रियाएं केवल कार्यस्थल के साथ विशिष्ट सीपीयू कोर निर्दिष्ट किए बिना:

TCP         - 25 microseconds
Named pipes - 15 microseconds

अब स्पष्ट रूप से मुख्य मुखौटे को निर्दिष्ट करना, जैसे कार्यपत्रक 1 जावा Srv या कार्यपत्रक 2 java Cli :

TCP, same cores:                      30 microseconds
TCP, explicit different cores:        22 microseconds
Named pipes, same core:               4-5 microseconds !!!!
Named pipes, taskset different cores: 7-8 microseconds !!!!

इसलिए

TCP overhead is visible
scheduling overhead (or core caches?) is also the culprit

एक ही समय में थ्रेड। स्लीप (0) (जो स्ट्रेस शो एकल शेड्यूल_यिल्ड का कारण बनता है) (लिनक्स कर्नेल कॉल को निष्पादित किया जाता है) 0.3 माइक्रोसेकंड लेता है - इसलिए सिंगल कोर के लिए निर्धारित पाइप अभी भी बहुत अधिक ओवरहेड हैं

कुछ साझा मेमोरी माप: 14 सितंबर, 2009 - सोलेस सिस्टम्स ने आज घोषणा की कि इसका यूनिफाइड मैसेजिंग प्लेटफॉर्म एपीआई एक साझा मेमोरी ट्रांसपोर्ट का उपयोग करके 700 से कम नैनोसेकंड की औसत विलंबता प्राप्त कर सकता है। http://solacesystems.com/news/fastest-ipc-messaging/

पुनश्च - मेमोरी मैप की गई फ़ाइलों के रूप में अगले दिन साझा की गई मेमोरी की कोशिश की जाती है, अगर व्यस्त प्रतीक्षा स्वीकार्य है, तो हम इस तरह कोड के साथ एक बाइट पास करने के लिए 0.3 माइक्रोसेकंड के लिए विलंबता को कम कर सकते हैं:

MappedByteBuffer mem =
  new RandomAccessFile("/tmp/mapped.txt", "rw").getChannel()
  .map(FileChannel.MapMode.READ_WRITE, 0, 1);

while(true){
  while(mem.get(0)!=5) Thread.sleep(0); // waiting for client request
  mem.put(0, (byte)10); // sending the reply
}

नोट: Thread.sleep (0) की आवश्यकता है इसलिए 2 प्रक्रियाएं एक दूसरे के परिवर्तन देख सकती हैं (मुझे अभी तक दूसरे तरीके का पता नहीं है)। यदि कार्यपत्रक के साथ एक ही कोर के लिए मजबूर 2 प्रक्रियाएं, विलंबता 1.5 माइक्रोसेकंड हो जाती है - यह एक संदर्भ स्विच देरी है

पीपीएस - और 0.3 माइक्रोसेकंड एक अच्छी संख्या है! केवल एक आदिम स्ट्रिंग संघनन करते समय निम्नलिखित कोड ठीक 0.1 माइक्रोसेकंड लेता है:

int j=123456789;
String ret = "my-record-key-" + j  + "-in-db";

PPPS - आशा है कि यह बहुत अधिक विषय नहीं है, लेकिन आखिरकार मैंने थ्रेड.सलीप (0) को बदलने की कोशिश की, जिसमें स्टैटिक वाष्पशील इंट वैरिएबल (JVM ऐसा करने पर सीपीयू कैश फ्लश करने के लिए होता है) और प्राप्त हुआ! - रिकॉर्ड - 72 नैनोसेकंड विलंबता जावा-टू-जावा प्रक्रिया संचार !

जब एक ही सीपीयू कोर के लिए मजबूर किया जाता है, हालांकि, अस्थिर-वृद्धिशील जेवीएम कभी भी एक-दूसरे को नियंत्रण नहीं देते हैं, इस प्रकार 10 मिलीसेकंड विलंबता का उत्पादन होता है - लिनक्स समय क्वांटम 5ms लगता है ... इसलिए इसका उपयोग केवल तभी किया जाना चाहिए जब कोई अतिरिक्त कोर हो - अन्यथा नींद (0) अधिक सुरक्षित है।


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

तो थ्रेड (स्लीप) को बदलने के साथ वाष्पशील स्थिर इंट को बढ़ाना चाहिए केवल तभी किया जाना चाहिए जब आप विभिन्न कोर पर प्रक्रिया कर सकते हैं? इसके अलावा, मुझे नहीं पता था कि आप ऐसा कर सकते हैं? मैंने सोचा कि ओएस फैसला करता है?
mezamorphic

3
LockSupport.parkNanos (1) आज़माएं, वही काम करना चाहिए।
reccles

बहुत अच्छा। हालांकि आप TCP पिंग के लिए बेहतर (5-7us RTT विलंबता के रूप में) कर सकते हैं। यहां देखें: psy-lob-saw.blogspot.com/2012/12/…
Nitsan Wakart

1
जावा में IPC कतार का समर्थन करने के लिए साझा की गई मेमोरी के रूप में मेमोरी मैप्ड फ़ाइल का उपयोग करने का और अन्वेषण: psy-lob-saw.blogspot.com/2013/04/lock-free-ipc-queue.html 135M संदेशों को प्राप्त करने के बाद दूसरा। विधि द्वारा विलंबता के तुलनात्मक अध्ययन के लिए नीचे मेरा उत्तर भी देखें।
निट्सन वकार्ट

10

डीएमए एक ऐसी विधि है जिसके द्वारा हार्डवेयर डिवाइस सीपीयू को बाधित किए बिना भौतिक रैम तक पहुंच सकते हैं। उदाहरण के लिए एक सामान्य उदाहरण हार्डडिस्क नियंत्रक है जो डिस्क से रैम तक सीधे बाइट्स कॉपी कर सकता है। जैसे कि यह IPC पर लागू नहीं है।

साझा मेमोरी और पाइप दोनों आधुनिक ओएस द्वारा सीधे समर्थित हैं। जैसे, वे काफी तेज हैं। कतारें आमतौर पर सार होती हैं, उदाहरण के लिए सॉकेट, पाइप और / या साझा मेमोरी के शीर्ष पर लागू की जाती हैं। यह एक धीमा तंत्र की तरह लग सकता है, लेकिन विकल्प यह है कि आप इस तरह के अमूर्त का निर्माण करें।


डीएमए के लिए, ऐसा क्यों है कि मैं आरडीएमए (रिमोट डायरेक्ट मेमोरी एक्सेस के रूप में) से संबंधित बहुत सी चीजें पढ़ सकता हूं जो कि पूरे नेटवर्क पर लागू होगी (विशेषकर InfiniBand के साथ) और यही काम करें। मैं वास्तव में नेटवर्क के बिना समकक्ष प्राप्त करने की कोशिश कर रहा हूं (जैसा कि सभी एक ही बॉक्स पर है)।
बैस्टियन

आरडीएमए एक ही अवधारणा है: दोनों तरफ सीपीयू को बाधित किए बिना एक नेटवर्क पर बाइट्स की प्रतिलिपि बनाना। यह अभी भी प्रक्रिया स्तर पर काम नहीं करता है।
एमएसलटर्स

10

सवाल कुछ समय पहले पूछा गया था, लेकिन आपको https://github.com/peter-lawrey/Java-Chronicle में रुचि हो सकती है जो 200 ns और 20 M संदेश / सेकंड के थ्रूपुट की विशिष्ट विलंबता का समर्थन करता है। यह प्रक्रियाओं के बीच साझा की गई मेमोरी मैप की गई फ़ाइलों का उपयोग करता है (यह डेटा को भी बनाए रखता है जो डेटा को बनाए रखने का सबसे तेज़ तरीका है)


7

यहां विभिन्न IPC ट्रांसपोर्ट के लिए प्रदर्शन परीक्षण युक्त एक परियोजना है:

http://github.com/rigtorp/ipc-bench


इसमें 'जावा फैक्टर' शामिल नहीं है, लेकिन यह दिलचस्प दिखता है।

6

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


6

देर से आगमन, लेकिन जावा एनआईओ का उपयोग करके पिंग विलंबता को मापने के लिए समर्पित एक खुला स्रोत परियोजना को इंगित करना चाहता था ।

इस ब्लॉग पोस्ट में आगे की खोज / व्याख्या की गई है । परिणाम (नैनो में आरटीटी) हैं:

Implementation, Min,   50%,   90%,   99%,   99.9%, 99.99%,Max
IPC busy-spin,  89,    127,   168,   3326,  6501,  11555, 25131
UDP busy-spin,  4597,  5224,  5391,  5958,  8466,  10918, 18396
TCP busy-spin,  6244,  6784,  7475,  8697,  11070, 16791, 27265
TCP select-now, 8858,  9617,  9845,  12173, 13845, 19417, 26171
TCP block,      10696, 13103, 13299, 14428, 15629, 20373, 32149
TCP select,     13425, 15426, 15743, 18035, 20719, 24793, 37877

यह स्वीकृत उत्तर की तर्ज पर है। System.nanotime () त्रुटि (कुछ नहीं मापने के द्वारा अनुमानित) को लगभग 40 नैनो पर मापा जाता है ताकि IPC के लिए वास्तविक परिणाम कम हो सके। का आनंद लें।


2

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


1

मेरी पूर्व कंपनी में हम इस परियोजना के साथ काम करते थे, http://remotetea.sourceforge.net/ , इसे समझना और एकीकृत करना बहुत आसान है।


0

क्या आपने सॉकेट्स को खुला रखने पर विचार किया है, ताकि कनेक्शन का पुन: उपयोग किया जा सके?


कुर्सियां ​​खुली रहती हैं। कनेक्शन पूरे समय के लिए जीवित है, जो अनुप्रयोग चल रहा है (लगभग 7 घंटे)। संदेशों का अधिक या कम लगातार आदान-प्रदान किया जाता है (मान लें कि लगभग 5 से 10 प्रति सेकंड)। वर्तमान विलंबता 200 माइक्रोसेकंड के आसपास है, लक्ष्य परिमाण के 1 या 2 आदेशों को शेव करना है।
बैस्टियन

एक 2 एमएस विलंबता? महत्वाकांक्षी। क्या साझा पुस्तकालय में सी-सामान को फिर से लिखना संभव होगा जिसे आप जेएनआई का उपयोग करने के लिए इंटरफ़ेस कर सकते हैं?
थोरबजोरन रावन एंडरसन

2ms 2000 माइक्रोसेकंड है, 200 नहीं। यह 2ms को कम महत्वाकांक्षी बनाता है।
thewhiteambit

-1

जेएनआई प्रदर्शन पर ओरेकल बग रिपोर्ट: http://bugs.java.com/bugdatabase/view_bug.do?bug_id=4096069

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


3
जेएनआई क्यों धीमा है? विचार करें कि जावा में निम्न स्तर की टीसीपी परत कैसे काम करती है, यह जावा बाइट-कोड में नहीं लिखा गया है! (उदाहरण के लिए इसे मूल होस्ट के माध्यम से फ़नल करना है।) इस प्रकार, मैं इस दावे को अस्वीकार करता हूं कि जावा टीसीपी सॉकेट जेएनआई की तुलना में अधिक तेज़ हैं। (JNI, हालाँकि, IPC नहीं है।)

4
यदि आप केवल प्राइमेटिव्स का उपयोग करते हैं, तो एक सिंगल जेएनआई कॉल आपको 9ns (इंटेल i5 पर) खर्च होता है। तो यह इतना धीमा नहीं है।
मार्टिन केर्स्टन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.