java - 无需复制即可快速读取缓冲区
问题描述
所以我有这个MappedByteBuffer,其中存储了一个 int 数组(从文件中读取)。
public static void read(String loc) {
try (FileChannel fileChannel = (FileChannel) Files.newByteChannel(
Paths.get(loc), EnumSet.of(StandardOpenOption.READ))) {
MappedByteBuffer mappedByteBuffer = fileChannel
.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size());
if (mappedByteBuffer != null) {
IntBuffer ib = mappedByteBuffer.asIntBuffer();
mappedByteBuffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
}
}
现在,当我想从 Buffer 中读取 int 数组并在我的代码中使用它时,我必须采用以下两种方式:
方式1:(将缓冲区(ints)的内容复制到一个int数组中)
int[] ar = new int[ib.capacity];
ib.get(ar);
int int_at_index_0 = ar[0];
方式2:(直接从缓冲区读取)
ib.get(0); //reads int at index 0 directly
现在据我了解,方式 1将存储在直接缓冲区上的数据复制到堆内存中,这是我不想要的,并且违背了使用堆外存储方式的目的。
方式 2 get(index)
方法的时间太长了,如下面的数据所示:
从数组中读取int[]
:(从 ByteBuffer 复制)
ar[0]
需要1928纳秒。
直接从 ByteBuffer 读取:
ib.get(0)
需要18915纳秒。
巨大差距。
有谁知道我如何从 directbuffer/mappedbytebuffer FAST中读取而不复制到堆内存(将其保存在堆外)。
解决方案
你可以像 Guava 的家伙在 ThreadLocal 中存储一个小缓冲区(1024 字节)那样做,如果它足够了就使用它,并且永远不要在 TL 中放置一个更大的缓冲区。
只要它可以处理大多数请求,这就会正常工作。没有一些真正的测试,很难判断它是否有帮助。
Google Guava ByteSource 似乎是在内存中缓冲的好选择。与 ByteArrayOutputStream 或 ByteArrayList(来自 Colt Library)之类的实现不同,它不会将数据合并到一个巨大的字节数组中,而是单独存储每个块。一个例子:
List<ByteSource> result = new ArrayList<>();
try (InputStream source = httpRequest.getInputStream()) {
byte[] cbuf = new byte[CHUNK_SIZE];
while (true) {
int read = source.read(cbuf);
if (read == -1) {
break;
} else {
result.add(ByteSource.wrap(Arrays.copyOf(cbuf, read)));
}
}
}
ByteSource body = ByteSource.concat(result);
ByteSource 可以在以后随时读取为 InputStream:
InputStream data = body.openBufferedStream();
[Also you might check this out ][1]
推荐阅读
- sql - postgresql 搜索 jsonb 数组项
- c# - 如何将产品信息附加到 xml 序列化程序 dll
- git - 在拉取请求被批准之前,我可以在我的分支中提交吗?
- javascript - Array.prototype.indexOf() 在 React.js 中的工作方式是否不同
- ios - NativeScript-Vue RadList 在 IOS 上无法正常工作
- angular - 升级到 TypeScript 3.1.6(或更高版本)后编译错误
- c++ - 如何在不设置为最大化的情况下最大化尺寸?
- docker - docker 中的 Rust actix_web 无法实现,为什么?
- python - 在Python中清空列表的最快方法是什么
- c++ - 为什么即使我们将指针分配给NULL,指针的指向对象的大小也不为零?