2013-03-05 6 views
7

मैं जावा में लिखे गए किसी एप्लिकेशन के कुछ मानक कर रहा हूं। प्रयोगों के लिए यह बहुत महत्वपूर्ण है कि परिणाम पृष्ठ कैश से प्रभावित नहीं हैं (मैं लिनक्स का उपयोग कर रहा हूं)पृष्ठ कैश के बिना सभी आईओ करने के लिए JVM को मजबूर करें (उदा। O_DIRECT)

तो पृष्ठ कैश से बचने का सबसे अच्छा तरीका O_DIRECT का उपयोग कर रहा है जब भी कोई फ़ाइल खोली जाती है। इसलिए मैंने जेरे के स्रोत कोड में संबंधित कोड बदल दिया।

मेरा दृष्टिकोण FileOutputStream (उदा। लेखन) के माध्यम से जाने वाली सभी चीज़ों के लिए पूरी तरह से काम करता है, लेकिन यह FileInputStream (उदा। पढ़ने) के लिए काम नहीं करता है।

जब FileInputStream की खुली कॉल करने के लिए O_DIRECT जोड़ने, JVM किसी भी कक्षा लोड करने में असमर्थ है: बस एक "unhacked का उपयोग करके

Error: Could not find or load main class perf.TestDirectIO 

यह त्रुटि एक classpath मुद्दा नहीं है, के बाद से मैं इसे ठीक कर सकते हैं "जेवीएम।

तो फाइलें खोलने के साथ एक समस्या प्रतीत होती है।

मैं इस मुद्दे को ठीक करने के तरीके पर किसी भी सलाह के बारे में बहुत खुश हूं।

यदि कोई भी कभी ऐसा कुछ करना चाहता है, तो मेरे पास documented the whole hack in my blog है।

jdk/src/share/native/java/io/FileInputStream.c:

@@ -58,7 +60,8 @@ 
JNIEXPORT void JNICALL 
Java_java_io_FileInputStream_open(JNIEnv *env, jobject this, jstring path) { 
- fileOpen(env, this, path, fis_fd, O_RDONLY); 
+ fileOpen(env, this, path, fis_fd, O_RDONLY | O_DIRECT); // this is the change that causes all the problems 
} 

यह परिवर्तन काम करता है: jdk/src/solaris/native/java/io/FileOutputStream_md.c:

@@ -55,8 +55,10 @@ 
JNIEXPORT void JNICALL 
Java_java_io_FileOutputStream_open(JNIEnv *env, jobject this, 
            jstring path, jboolean append) { 
    fileOpen(env, this, path, fos_fd, 
-    O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC)); 
+    O_WRONLY | O_DIRECT | O_CREAT | (append ? O_APPEND : O_TRUNC)); 
} 


एक संदर्भ के रूप में, इन JVM कोड मैं वैसा ही किया पर परिवर्तन कर रहे हैं मैंने टी को सुनिश्चित करने के लिए हॉटस्पॉट जेरे भी बदल दिया

+# include <mm_malloc.h> 
... 
- u_char* ptr = (u_char*)::malloc(size + space_before + space_after); 
+ u_char* ptr = (u_char*)::_mm_malloc(size + space_before + space_after,512); 
+0

क्या आप पुराने और नए जेडीके दोनों के लिए 'strace -f' के आउटपुट की तुलना कर सकते हैं? मुझे लगता है, कुछ I/O कोड विफल रहता है, उदा। O_DIRECT सीमाओं के कारण पढ़ने के सिस्कोल पर (चेक 'मैन 2 ओपन', सेक्शन नोट्स => ओ_DIRECT) – osgx

+0

यहां स्ट्रेस आउटपुट है: http://privatepaste.com/download/a1ef2d78ac I मुझे कोई स्पष्ट कारण नहीं दिख रहा है विफलता। –

+0

आपने अनलिखित आकार के साथ 'पढ़ा' है जिसके परिणामस्वरूप EINVAL त्रुटि हुई है (कोई फ़ॉलबैक लागू नहीं किया गया था)। – osgx

उत्तर

6
"The thing that has always disturbed me about O_DIRECT is that the 
    whole interface is just stupid, and was probably designed by a deranged 
    monkey on some serious mind-controlling substances [*]." 

[*] दूसरे शब्दों में, यह एक Oracleism है: टोपी स्मृति गठबंधन है hotspot/src/share/vm/runtime/os.cpp (O_DIRECT के लिए एक आवश्यकता thats)।

O_DIRECT

लिये O_DIRECT फ्लैग संरेखण लंबाई पर प्रतिबंध लागू और यूज़रस्पेस बफ़र्स की संबोधित कर सकते हैं और: -

Linus Torvalds from Transmeta, 11 May 2002

चेक man 2 open की धारा नोट्स I12 के फ़ाइल ऑफसेट ऑफ़सेट करें। लिनक्स संरेखण में प्रतिबंध फाइल सिस्टम और कर्नेल संस्करण के हिसाब से बदलती ....

लिनक्स 2.4, स्थानांतरण आकार, और उपयोगकर्ता बफर के संरेखण और फ़ाइल ऑफसेट सभी की तार्किक ब्लॉक आकार के गुणकों में होना चाहिए के तहत फ़ाइल प्रणाली। लिनक्स 2 के तहत।6, संरेखण 512-बाइट सीमाओं के लिए पर्याप्त है। ....

संक्षेप में, O_DIRECT एक संभावित शक्तिशाली उपकरण है जिसका उपयोग सावधानी के साथ किया जाना चाहिए। यह अनुशंसा की जाती है कि अनुप्रयोग O_DIRECT के उपयोग को प्रदर्शन विकल्प के रूप में उपयोग करें जो डिफ़ॉल्ट रूप से अक्षम है।

मुझे लगता है कि, वहाँ JRE (classloader) में FileInputStream जो ऑफसेट के साथ पढ़ता है या 512 बाइट्स के अनुरूप नहीं आकार के कुछ उपयोगों के हैं। (। Advanced Format के लिए कम से कम संरेखण भी 4096 बाइट्स, या एक 4K पेज बड़ा हो सकता है,)

असंरेखित ऑफसेट के लिए कर्नेल के व्यवहार ग्रे क्षेत्र है, कुछ जानकारी यहाँ है: RFC: Clarifying Direct I/O Semantics, Theodore Ts'o, [email protected], LWN, 2009

अन्य रोचक चर्चा है यहां: Linux: Accessing Files With O_DIRECT (कर्नेलटेल, 2007)

हम्म, ऐसा लगता है कि प्रत्यक्ष विफलता के साथ कुछ I/O buffered करने के लिए फ़ॉलबैक होना चाहिए। DIRECT के साथ सभी आईओ संचालन तुल्यकालिक हैं। कुछ डीएमए प्रभाव हो सकता है? या O_DIRECT और mmap का संयोजन?

अद्यतन:

strace उत्पादन के लिए धन्यवाद। यहाँ त्रुटि (grep O_DIRECT, तो फ़ाइल वर्णनकर्ता कार्रवाई जांचने) है:

28290 open("...pact/perf/TestDirectIO.class", O_RDONLY|O_DIRECT) = 11 
28290 fstat(11, {st_mode=S_IFREG|0644, st_size=2340, ...}) = 0 
28290 fcntl(11, F_GETFD)    = 0 
28290 fcntl(11, F_SETFD, FD_CLOEXEC) = 0 
...skip 
28290 stat("...pact/perf/TestDirectIO.class", {st_mode=S_IFREG|0644, st_size=2340, ...}) = 0 
...skip 
28290 read(11, "\312\376\272\276\0\0\0003\0\215\n\0-\0D\t\0E\0F\7\0G\n\0\3\0D\10\0H\n"..., 1024) = 1024 
28290 read(11, 0x7f1d76d23a00, 1316) = -1 EINVAL (Invalid argument) 

EINVAL त्रुटि में असंरेखित पढ़ने आकार का परिणाम है। आपकी क्लासफ़ाइल 2340 बाइट लंबी है, यह 1024 + 1316 बाइट्स है, जो गठबंधन नहीं है।

+1

लिनस द्वारा कुछ अन्य उद्धरण दिए गए हैं: http://kerneltrap.org/node/7563 –

+0

बस एक ही पल में उसी पृष्ठ को पढ़ना। जोड़ा गया। अब मैं वास्तविक कर्नेल कोड की जांच करूंगा, क्या आप अपने परीक्षण में उपयोग किए गए सटीक कर्नेल संस्करण और फाइल सिस्टम का उपयोग कर सकते हैं (ext3, ext4, ..)? – osgx

+0

मैं अभी भी आपको स्ट्रेस आउटपुट देने पर काम कर रहा हूं। पेस्टबिन और gist.github उनकी परेशानी है। मैं ext4, और एक 3.7.9 कर्नेल (आर्क लिनक्स) का उपयोग कर रहा हूं। –

8

पुरानी पोस्ट, लेकिन मैंने हाल ही में Jaydio नामक एक छोटी लाइब्रेरी लिखी है जो इस सटीक समस्या को हल करने की उम्मीद कर रही है। शायद आप इसे उपयोगी पाएंगे।

+0

बढ़िया! आपकी लाइब्रेरी वास्तव में अच्छी लगती है! (और उपयोगकर्ता को एक कस्टम JVM संस्करण संकलित करने की आवश्यकता नहीं है)। मुझे यकीन नहीं है कि मैं आपको स्वीकार्य उत्तर दे सकता हूं क्योंकि @osgx ने मुझे अपने उत्तर के साथ बहुत मदद की। लेकिन मुझे उम्मीद है कि एसओ समुदाय आपको वोट देगा! –

+0

धन्यवाद! यह बहुत उपयोगी रहा है। –

2

आप जावा के तहत O_DIRECT का उपयोग कर सकते हैं, Java Native Access (JNA) का लाभ उठा सकते हैं। इनपुट स्ट्रीम और आउटपुटस्ट्रीम के लिए कार्यान्वयन, O_DIRECT सक्षम के साथ, here प्रदान किए जाते हैं।

संबंधित मुद्दे

 संबंधित मुद्दे