फ़ाइल फ़ाइल में डेटा कैसे लिखा जा सकता है वास्तव में जावा द्वारा ब्लॉक डिवाइस के साथ फ़्लश/सिंक किया जा सकता है।जावा में फ़ाइल सिंक/फ्लश को वास्तव में मजबूर करें
मैं NIO के साथ इस कोड की कोशिश की:। S.getFD() के साथ
FileOutputStream s = new FileOutputStream(filename)
Channel c = s.getChannel()
while(xyz)
c.write(buffer)
c.force(true)
s.getFD().sync()
c.close()
मुझे लगता है कि c.force (सही) माना जाता togehter सिंक() पर्याप्त होना चाहिए क्योंकि force राज्यों
के लिए दस्तावेज़इस चैनल की फ़ाइल के किसी भी अपडेट को उस स्टोरेज डिवाइस पर लिखा जा सकता है जिसमें यह शामिल है। यदि यह चैनल की फ़ाइल स्थानीय स्टोरेज डिवाइस पर रहता है तो जब यह विधि लौटाती है तो यह गारंटी दी जाती है कि इस चैनल के निर्माण के बाद से फ़ाइल में किए गए सभी परिवर्तन, या चूंकि इस विधि को अंतिम बार बुलाया गया था, तो उस डिवाइस पर लिखा होगा। यह सुनिश्चित करने के लिए उपयोगी है कि सिस्टम क्रैश होने की स्थिति में महत्वपूर्ण जानकारी खो नहीं जाती है।
प्रलेखन sync को कहता है:
फोर्स सभी सिस्टम बफ़र्स अंतर्निहित डिवाइस के साथ सिंक्रनाइज़ करने के लिए। यह विधि सभी संशोधित डेटा के बाद लौटाती है और इस फ़ाइल डिस्क्रिप्टर के गुण प्रासंगिक डिवाइस (नों) में लिखे गए हैं। विशेष रूप से, यदि यह फ़ाइलडिस्क्रिप्टर भौतिक भंडारण माध्यम को संदर्भित करता है, जैसे फ़ाइल सिस्टम में फ़ाइल, सिंक तब तक वापस नहीं आ जाएगा जब तक कि इस फ़ाइल से जुड़े बफर की सभी इन-मेमोरी संशोधित प्रतियां भौतिक माध्यम पर लिखी गई हों। सिंक का उपयोग कोड द्वारा किया जाना है जिसके लिए एक ज्ञात स्थिति में भौतिक भंडारण (जैसे फ़ाइल) की आवश्यकता होती है।
ये दो कॉल पर्याप्त होनी चाहिए। क्या यह? मुझे लगता है कि वे नहीं हैं।
पृष्ठभूमि: मैं सी/जावा का उपयोग करके एक छोटी प्रदर्शन तुलना (2 जीबी, अनुक्रमिक लेखन) करता हूं और जावा संस्करण सी संस्करण के मुकाबले दो गुना तेज है और शायद हार्डवेयर से तेज (एक ही एचडी पर 120 एमबी/एस)। मैंने Runtime.getRuntime()। Exec ("sync") के साथ कमांड लाइन टूल सिंक निष्पादित करने का भी प्रयास किया लेकिन इसने व्यवहार को नहीं बदला है। अंतिम कॉल सिंक करने के लिए बिना
FILE* fp = fopen(filename, "w");
while(xyz) {
fwrite(buffer, 1, BLOCK_SIZE, fp);
}
fflush(fp);
fclose(fp);
sync();
;:
सी कोड 70 एमबी में जिसके परिणामस्वरूप/s है (कम स्तर एपीआई (का उपयोग कर खुला, लिखने, करीब) ज्यादा परिवर्तन नहीं करता है) मुझे अवास्तविक मूल्य मिले (1 जीबी उर्फ मुख्य मेमोरी प्रदर्शन)।
सी और जावा के बीच इतना बड़ा अंतर क्यों है? दो संभावनाएं हैं: मैं जावा में डेटा को सही तरीके से सिंक नहीं करता हूं या सी कोड कुछ कारणों से उप-स्थानिक है।
अद्यतन: मैंने "स्ट्रेस-सीएफटी सेमीडी" के साथ स्ट्रेस रन किए हैं।
सी (निम्न स्तर एपीआई): MB/s 67,389782
% time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 87.21 0.200012 200012 1 fdatasync 11.05 0.025345 1 32772 write 1.74 0.004000 4000 1 sync
सी (उच्च स्तर एपीआई): यहाँ के परिणाम हैं MB/s 61,796458
% time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 73.19 0.144009 144009 1 sync 26.81 0.052739 1 65539 write
जावा (1.6 सन जेआरई, जावा.आईओ एपीआई): एमबी/एस 128।6755466197537
% time seconds usecs/call calls errors syscall ------ ----------- ----------- --------- --------- ---------------- 80.07 105.387609 3215 32776 write 2.58 3.390060 3201 1059 read 0.62 0.815251 815251 1 fsync
जावा (1.6 रवि JRE, java.nio एपीआई): MB/s 127,45830221558376
5.52 0.980061 490031 2 fsync 1.60 0.284752 9 32774 write 0.00 0.000000 0 80 close
समय मान सिस्टम का समय केवल होने लगते हैं और इसलिए बहुत व्यर्थ कर रहे हैं।
अपडेट 2: मैंने दूसरे सर्वर पर स्विच किया, रीबूट किया, और मैं एक नया स्वरूपित ext3 का उपयोग करता हूं। अब मुझे जावा और सी के बीच केवल 4% अंतर मिलते हैं। मुझे नहीं पता कि क्या गलत हुआ। कभी-कभी चीजें अजीब होती हैं। इस प्रश्न को लिखने से पहले मुझे किसी अन्य प्रणाली के साथ माप की कोशिश करनी चाहिए थी। माफ़ कीजिये।
अद्यतन 3: जवाब संक्षेप में प्रस्तुत करने के लिए:।
- उपयोग c.force (सही) s.getFD() के बाद जावा NIO और s.flush() और s.getFD के लिए सिंक()() .sync() जावा के स्ट्रीम एपीआई के लिए। सी में उच्च स्तरीय एपीआई के लिए सिंक करना न भूलें। एक एफएफएलश ने ओएस को डेटा जमा किया, लेकिन ब्लॉक डेटा पर आपका डेटा नहीं लाता है।
- कमांड
- द्वारा किए गए सिस्कोल का विश्लेषण करने के लिए स्ट्रेस का उपयोग करें, प्रश्न पोस्ट करने से पहले अपने परिणामों की जांच करें।
अद्यतन 4: कृपया निम्नलिखित अनुवर्ती question पर ध्यान दें।
मैं वास्तव में केवल अनुभाग 2 फ़ंक्शंस का उपयोग करके थ्रूपुट देखना चाहता हूं। –
आप BLOCK_SIZE के लिए क्या उपयोग कर रहे हैं? क्या जावा में आपके बफर के समान आकार है? इन दिनों 512 बहुत उपोष्णकटिबंधीय होने जा रहा है। आप शायद कम से कम 4096 (x86 पर पेज आकार) या संभवतः उच्चतर चाहते हैं। मैंने कुछ मशीनों पर 32k तक मापनीय सुधार देखा है। ओह, और निश्चित रूप से यदि आपका बफर पेज-गठबंधन है तो यह कर्नेल को ऑप्टिमाइज़ेशन के लिए और अधिक जगह देगा। – aij
एक और संभावित मुद्दा यह है कि आपके द्वारा पोस्ट किया गया कोड "निम्न स्तर के एपीआई (खुला, लिखना, बंद)" का उपयोग नहीं कर रहा है। यह उच्च स्तर, पोर्टेबल stdio API (fopen, fwrite, fclose) का उपयोग कर रहा है जो डिफ़ॉल्ट रूप से बफरिंग की एक अतिरिक्त परत जोड़ देगा। क्या आपने स्पष्ट रूप से आपके द्वारा पोस्ट किए गए कोड के बाहर कहीं बफरिंग बंद कर दी है? – aij