¿Por qué el diferencial de curva de rendimiento impar entre ByteBuffer.allocate () y ByteBuffer.allocateDirect ()

Estoy trabajando en algoSocketChannel-a-SocketChannel código que funcionará mejor con un búfer de bytes directos: de larga duración y de gran tamaño (decenas a cientos de megabytes por conexión).FileChannels, ejecuté algunos micro-puntos de referencia enByteBuffer.allocate() vs.ByteBuffer.allocateDirect() actuación.

Hubo una sorpresa en los resultados que realmente no puedo explicar. En el gráfico a continuación, hay un acantilado muy pronunciado en los 256 KB y 512 KB para elByteBuffer.allocate() Implementación de transferencia: ¡el rendimiento se reduce en ~ 50%! También parece haber un pequeño acantilado de rendimiento para elByteBuffer.allocateDirect(). (La serie% -gain ayuda a visualizar estos cambios).

Tamaño del búfer (bytes) frente al tiempo (MS)

¿Por qué la extraña curva de rendimiento diferencial entreByteBuffer.allocate() yByteBuffer.allocateDirect()? ¿Qué está pasando exactamente detrás de la cortina?

Es muy posible que dependa del hardware y del sistema operativo, así que aquí están esos detalles:

MacBook Pro con CPU de doble núcleo Core 2Unidad SSD Intel X25MOSX 10.6.4

Código fuente, por solicitud:

package ch.dietpizza.bench;

import static java.lang.String.format;
import static java.lang.System.out;
import static java.nio.ByteBuffer.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;

public class SocketChannelByteBufferExample {
    private static WritableByteChannel target;
    private static ReadableByteChannel source;
    private static ByteBuffer          buffer;

    public static void main(String[] args) throws IOException, InterruptedException {
        long timeDirect;
        long normal;
        out.println("start");

        for (int i = 512; i <= 1024 * 1024 * 64; i *= 2) {
            buffer = allocateDirect(i);
            timeDirect = copyShortest();

            buffer = allocate(i);
            normal = copyShortest();

            out.println(format("%d, %d, %d", i, normal, timeDirect));
        }

        out.println("stop");
    }

    private static long copyShortest() throws IOException, InterruptedException {
        int result = 0;
        for (int i = 0; i < 100; i++) {
            int single = copyOnce();
            result = (i == 0) ? single : Math.min(result, single);
        }
        return result;
    }


    private static int copyOnce() throws IOException, InterruptedException {
        initialize();

        long start = System.currentTimeMillis();

        while (source.read(buffer)!= -1) {    
            buffer.flip();  
            target.write(buffer);
            buffer.clear();  //pos = 0, limit = capacity
        }

        long time = System.currentTimeMillis() - start;

        rest();

        return (int)time;
    }   


    private static void initialize() throws UnknownHostException, IOException {
        InputStream  is = new FileInputStream(new File("/Users/stu/temp/robyn.in"));//315 MB file
        OutputStream os = new FileOutputStream(new File("/dev/null"));

        target = Channels.newChannel(os);
        source = Channels.newChannel(is);
    }

    private static void rest() throws InterruptedException {
        System.gc();
        Thread.sleep(200);      
    }
}

Respuestas a la pregunta(4)

Su respuesta a la pregunta