2012-02-05 10 views
6

मैंने हाल ही में पढ़ा है कि नए कंप्यूटरों में जावा के आई/ओ बहु-कोर मशीनों की नई उपलब्धता के कारण एनआईओ से बेहतर प्रदर्शन करता है।जावा I/O बनाम एनआईओ: त्वरित बेंचमार्क तुलना

मैंने स्थानीयहोस्ट लूपबैक पते का उपयोग कर लैन पर आई/ओ और एनआईओ के स्थानांतरण समय की तुलना में एक त्वरित परीक्षण चलाया।

नोट:

आई/ओ स्थानान्तरण औसतन 21789.3ms

NIO स्थानान्तरण औसतन 22771.0ms

: इस JDK का उपयोग कर 7

परिणाम (3 परीक्षणों) है यह ध्यान देने योग्य भी है कि I/O की तुलना में प्रत्येक एनआईओ हस्तांतरण पर CPU उपयोग लगभग 10% अधिक दिखाई देता है।

मेरा प्रश्न आपके लिए है यदि मेरा तुलना कोड उचित है? क्या मैंने अच्छा/बराबर I/O और एनआईओ कोड लिखा था? यदि नहीं, तो मैं इस परीक्षण को कैसे सुधार और पुन: चला सकता हूं?

public static void main(String[] args) { 
    System.out.println("Initiating test sequence..."); 
    new Thread(new Client()).start(); 
    try { 
     System.out.println("Server I/O initiating..."); 
     ServerSocket server = new ServerSocket(5555); 
     Socket sock = server.accept(); 
     System.out.println("Server connected to client successfully"); 
     InputStream is = sock.getInputStream(); 
     File output = new File("C:/test_root/video.avi"); 
     FileOutputStream fos = new FileOutputStream(output); 
     byte[] data = new byte[1024]; 
     int len=0; 
     System.out.println("Server initiating transfer - Timer starting"); 
     long start = System.currentTimeMillis(); 
     while((len=is.read(data))>0) { 
      fos.write(data, 0, len); 
      fos.flush(); 
     } 
     fos.close(); 
     is.close(); 
     sock.close(); 
     server.close(); 
     long end = System.currentTimeMillis(); 
     System.out.println("Network I/O transfer time = "+(end-start)+"ms"); 

     System.out.println("Server NIO initiating..."); 
     ServerSocketChannel serverChan = ServerSocketChannel.open(); 
     serverChan.bind(new InetSocketAddress(5555)); 
     SocketChannel chan = serverChan.accept(); 
     chan.configureBlocking(false); 
     System.out.println("Server channel connected"); 
     FileChannel fc = (FileChannel) Files.newByteChannel(Paths.get("C:/test_root/video.avi"), StandardOpenOption.CREATE, StandardOpenOption.WRITE); 
     ByteBuffer buff = ByteBuffer.allocate(1024); 
     System.out.println("Server initiating transfer - Timer starting"); 
     start = System.currentTimeMillis(); 
     while(chan.read(buff)>=0 || buff.position() > 0) { 
      buff.flip(); 
      fc.write(buff); 
      buff.compact(); 
     } 
     chan.close(); 
     fc.close(); 
     serverChan.close(); 
     end = System.currentTimeMillis(); 
     System.out.println("Network NIO transfer time = "+(end-start)+"ms"); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    System.out.println("Test completed!"); 
} 

static class Client implements Runnable { 

    public void run() { 
     try { 
      System.out.println("Client I/O initiating..."); 
      Socket sock = new Socket("localhost", 5555); 
      System.out.println("Client connected to server successfully!"); 
      OutputStream os = sock.getOutputStream(); 
      File input = new File(System.getProperty("user.home")+"/Documents/clip0025.avi"); 
      FileInputStream fis = new FileInputStream(input); 
      byte[] data = new byte[1024]; 
      int len=0; 
      int tot=0; 
      int perc=0; 
      while((len=fis.read(data))>0) { 
       os.write(data, 0, len); 
       os.flush(); 
       tot+=len; 
       int prev = perc; 
       perc = getPercentage(tot, input.length()); 
       if(perc !=prev && (perc == 10 || perc == 25 || perc == 50 || perc == 75 || perc == 98)) 
        System.out.println("Client reporting: "+perc+"% read"); 
      } 
      os.close(); 
      fis.close(); 
      sock.close(); 

      try { 
       Thread.sleep(2000); 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
      System.out.println("Client NIO initiating..."); 
      SocketChannel sc = SocketChannel.open(); 
      boolean connected = sc.connect(new InetSocketAddress("localhost",5555)); 
      if(!connected) 
       connected = sc.finishConnect(); 
      if(!connected) 
       throw(new IOException("Client failed to connect")); 
      System.out.println("Client channel connected"); 
      sc.configureBlocking(false); 
      FileChannel fc = (FileChannel) Files.newByteChannel(input.toPath(), StandardOpenOption.READ); 
      ByteBuffer buff = ByteBuffer.allocate(1024); 
      len=0; 
      tot=0; 
      while((len=fc.read(buff))>=0||buff.position()>0) { 
       buff.flip(); 
       sc.write(buff); 
       buff.compact(); 
       tot+=len; 
       int prev = perc; 
       perc = getPercentage(tot, input.length()); 
       if(perc !=prev && (perc == 10 || perc == 25 || perc == 50 || perc == 75 || perc == 98)) 
        System.out.println("Client reporting: "+perc+"% read"); 
      } 
      sc.close(); 
      fc.close(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

अतिरिक्त जानकारी:

विंडोज विस्टा (SP2) डेल स्टूडियो पर एक्सपीएस 435MT

1 जनरल i7 क्वाड-कोर प्रोसेसर 2.67GHz

6GB रैम

64-बिट वास्तुकला

+1

मुझे विश्वास है कि इस की बेंच मार्किंग हिस्सा उचित है नहीं कर रहा हूँ - जावा में, तुम सच में JVM और सभी को गर्म की तरह कार्य करने की आवश्यकता है। आप http://code.google.com/p/caliper/ जैसे बेंचमार्किंग टूल का उपयोग करने में सक्षम हो सकते हैं। –

+0

@LouisWasserman आप JVM को गर्म करने और/या इस कोड में सुधार करने का सुझाव कैसे देंगे? – bgroenks

+1

उन लोगों द्वारा निर्मित बेंचमार्किंग फ्रेमवर्क का उपयोग करें जो जानते हैं कि वे जेवीएम को अनिवार्य रूप से क्या कर रहे हैं। अपना खुद का "समय एक ऑपरेशन" कोड न लिखें। इसे सही करने के लिए गलत होने के कई और तरीके हैं। –

उत्तर

3

सुझाव

  • एनआईओ को अवरुद्ध करने के साथ अवरुद्ध आईओ की तुलना करने का प्रयास करें। आपका कोड छोटा होगा। यदि आप आईओ परीक्षण करने जा रहे हैं, तो क्लाइंट और सर्वर पर आईओ का उपयोग करें। यदि आप एनआईओ का उपयोग करने जा रहे हैं, तो दोनों सिरों पर इसका इस्तेमाल करें।
  • प्रत्यक्ष बाइटबफर का उपयोग करें।
  • फ़ाइलों को पढ़ने/लिखना न करें क्योंकि वे बेंचमार्क का हिस्सा नहीं हैं और बहुत धीमे हो सकते हैं। बस डेटा के रिक्त ब्लॉक के चारों ओर पास करें।
  • विभिन्न ब्लॉक आकारों का प्रयास करें, उदा। 8 केबी
  • उस डेटा के प्रकार पर विचार करें जिसे आप एक्सचेंज करना चाहते हैं। जैसे बाइटबफर int और long और अधिक कुशल पढ़ सकता है।
  • बैंडविड्थ के संदर्भ में रिपोर्ट संख्याएं। मैं लूप वापस 1-3 जीबी/सेकेंड के बीच देखने की उम्मीद करता हूं।

http://vanillajava.blogspot.com/2010/07/java-nio-is-faster-than-java-io-for.html

+0

सुझावों के लिए धन्यवाद। – bgroenks

+0

आपको लिंक दिलचस्प लगेगा। –

+0

मॉडल थ्रेडिंग से उसका क्या मतलब है? – bgroenks

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