¿Por qué el flujo paralelo de Files.list () funciona mucho más lento que con Collection.parallelStream ()?

El siguiente fragmento de código es parte de un método que obtiene un listado de directorio, llama a un método de extracción en cada archivo y serializa el objeto de fármaco resultante a xml.

try(Stream<Path> paths = Files.list(infoDir)) {
    paths
        .parallel()
        .map(this::extract)
        .forEachOrdered(drug -> {
            try {
                marshaller.write(drug);
            } catch (JAXBException ex) {
                ex.printStackTrace();
            }
        });
}

Aquí está exactamente el mismo código haciendo exactamente lo mismo pero usando un simple.list() llame para obtener el listado del directorio y llamar.parallelStream() en la lista resultante.

Arrays.asList(infoDir.toFile().list())
    .parallelStream()
    .map(f -> infoDir.resolve(f))
    .map(this::extract)
    .forEachOrdered(drug -> {
        try {
            marshaller.write(drug);
        } catch (JAXBException ex) {
            ex.printStackTrace();
    }
});

Mi máquina es una MacBook Pro de cuatro núcleos, Java v 1.8.0_60 (compilación 1.8.0_60-b27).

Estoy procesando ~ 7000 archivos. Los promedios de 3 carreras:

Primera versión: con.parallel(): 20 segundos. Sin.parallel(): 41 segundos

Segunda versión: con.parallelStream(): 12 segundos. Con.stream(): 41 segundos.

Esos 8 segundos en modo paralelo parecen una enorme diferencia dado que elextract método que lee de la secuencia y hace todo el trabajo pesado y elwrite la llamada que realiza las escrituras finales no se modifica.

Respuestas a la pregunta(3)

Su respuesta a la pregunta