Eu tenho um CSV
arquivo de 35GB . Quero ler cada linha e gravar a linha em um novo CSV, se corresponder a uma condição.
try (BufferedWriter writer = Files.newBufferedWriter(Paths.get("source.csv"))) {
try (BufferedReader br = Files.newBufferedReader(Paths.get("target.csv"))) {
br.lines().parallel()
.filter(line -> StringUtils.isNotBlank(line)) //bit more complex in real world
.forEach(line -> {
writer.write(line + "\n");
});
}
}
Isso leva aprox. 7 minutos. É possível acelerar ainda mais esse processo?
java
java-stream
java-io
som do membro
fonte
fonte
parallel
torna mais rápido? E isso não embaralha as linhas?BufferedWriter
você mesmo, usando o construtor que permite definir o tamanho do buffer. Talvez um tamanho de buffer maior (ou menor) faça a diferença. Eu tentaria corresponder oBufferedWriter
tamanho do buffer ao tamanho do buffer do sistema operacional do host.Respostas:
Se for uma opção, você poderá usar GZipInputStream / GZipOutputStream para minimizar a E / S do disco.
O Files.newBufferedReader / Writer usa um tamanho de buffer padrão, 8 KB, acredito. Você pode tentar um buffer maior.
A conversão para String, Unicode, diminui para (e usa o dobro da memória). O UTF-8 usado não é tão simples quanto StandardCharsets.ISO_8859_1.
O melhor seria se você pudesse trabalhar com bytes na maior parte e apenas para campos CSV específicos convertê-los em String.
Um arquivo mapeado de memória pode ser o mais apropriado. O paralelismo pode ser usado por intervalos de arquivos, cuspindo o arquivo.
Isso se tornará um pouco demais de código, colocando as linhas corretamente
(byte)'\n'
, mas não excessivamente complexo.fonte
GZipInputStream + GZipOutputStream
totalmente a memória em um ramdisk. O desempenho foi muito pior ...MappedByteBuffer
partir da última posiçãoFileChannel.map
válida ( leva muito tempo).new RandomAccessFile(…).getChannel()
. Apenas useFileChannel.open(…)
.você pode tentar isso:
Eu acho que você vai economizar um ou dois minutos. o teste pode ser feito na minha máquina em cerca de 4 minutos, especificando o tamanho do buffer.
poderia ser mais rápido? tente isto:
Isso deve economizar três ou quatro minutos.
Se isso ainda não é suficiente. (A razão pela qual acho que você faz a pergunta provavelmente é que você precisa executar a tarefa repetidamente). se você quiser fazê-lo em um minuto ou até alguns segundos. você deve processar os dados e salvá-los no banco de dados, depois processar a tarefa por vários servidores.
fonte
cbuf
conteúdo e escrever apenas partes? E eu teria que redefinir o buffer uma vez cheio? (como posso saber se o buffer está cheio?) #Graças a todas as suas sugestões, o mais rápido que eu vim foi trocar o escritor, o que resultou em uma
BufferedOutputStream
melhoria de aproximadamente 25%:Ainda assim, o
BufferedReader
desempenho é melhor do queBufferedInputStream
no meu caso.fonte