Java I / O vs NIO: Comparaison rapide des Benchmarks


J'ai récemment lu que dans les ordinateurs plus récents, les E/S de Java fonctionnent mieux que NIO en raison de la nouvelle disponibilité des machines multi-cœurs.

J'ai effectué un test rapide comparant le temps de transfert des E/S et des NIO sur le réseau local en utilisant l'adresse de bouclage localhost.

Remarque: Cela utilise JDK 7

Les résultats (3 essais):

Transferts d'e/S en moyenne 21789.3 ms

Transferts NIO en moyenne 22771.0 ms

Il vaut également la peine notant que l'utilisation du PROCESSEUR semblait être environ 10% plus élevée sur chaque transfert NIO par rapport aux E/S.

Ma question pour vous est de savoir si mon code de comparaison est juste? Ai-je écrit du code d'E/S et NIO bon/égal? Sinon, comment puis-je améliorer et relancer ce test?

    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();
        }
    }
}

Informations supplémentaires:

Il est possible d'utiliser Windows Vista (SP2) sur Dell Studio XPS 435MT

1ère génération i7 quad-core processeur 2.67 GHz

6 Go DE RAM

Architecture 64 bits

Author: bgroenks, 2012-02-05

1 answers

Suggestions

  • Essayez de comparer le blocage IO avec le blocage NIO. Votre code sera plus court. Si vous allez tester IO, utilisez IO sur le client et le serveur. Si vous allez utiliser NIO, utilisez la même chose aux deux extrémités.
  • Utilisez des ByteBuffers directs.
  • Ne pas lire/écrire dans les fichiers car ils ne font pas partie du benchmark et peuvent être beaucoup plus lents. Il suffit de passer autour des blocs de données vierges.
  • Essayez différentes tailles de blocs, par exemple 8 Ko.
  • Considérez le type de données que vous souhaitez échange. par exemple, ByteBuffer peut rendre la lecture int et long plus efficace.
  • Nombre de rapports en termes de bande passante. Je m'attendrais à voir entre 1-3 GB / sec sur la boucle arrière.

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

 4
Author: Peter Lawrey, 2012-02-05 21:37:18