我有一个巨大的字节数组需要处理。理论上,应该可以将工作分成均匀的部分并将它们分配给不同的线程,以提高多核机器的性能。
我为每个线程分配了一个ByteBuffer
,并分别处理了部分数据。即使我有 8 个逻辑处理器,最终性能也比单线程慢。也是非常不协调的。有时,相同的输入处理速度会慢一倍或更多。这是为什么?数据首先加载到内存中,因此不再执行任何IO
操作。
我分配我的 ByteBuffers 使用MappedByteBuffer
,因为它比ByteBuffer.wrap()
:
public ByteBuffer getByteBuffer() throws IOException
{
File binaryFile = new File("...");
FileChannel binaryFileChannel = new RandomAccessFile(binaryFile, "r").getChannel();
return binaryFileChannel.map(FileChannel.MapMode.READ_ONLY, 0, binaryFileChannel.size());
}
我使用以下方法进行并发处理Executors
:
int threadsCount = Runtime.getRuntime().availableProcessors();
ExecutorService executorService = Executors.newFixedThreadPool(threadsCount);
ExecutorCompletionService<String> completionService = new ExecutorCompletionService<>(executorService);
for (ByteBufferRange byteBufferRange : byteBufferRanges)
{
Callable<String> task = () ->
{
performTask(byteBufferRange);
return null;
};
completionService.submit(task);
}
// Wait for all tasks to finish
for (ByteBufferRange ignored : byteBufferRanges)
{
completionService.take().get();
}
executorService.shutdown();
并发任务performTask()
使用它们自己的ByteBuffer
实例从缓冲区中读取内存、进行计算等。它们不同步、不写入或相互影响。任何想法出了什么问题,或者这不是并行化的好例子吗?
同样的问题也ByteBuffer.wrap()
存在MappedByteBuffer
。