首页 > 编程知识 正文

arraylist底层数据结构是,string底层数据结构是什么

时间:2023-05-04 02:14:22 阅读:19347 作者:3593

Java sendFile的底层实现

前言

Java send file api是transferTo和transferFrom方法。

注: send file是磁盘到网卡的I/o优化。 相反,从网卡到磁盘都没有此IO优化。 也就是说,transferFrom方法没有这种福利。

本文稍微详细地介绍了Java是如何实现的。 请注意。 本文的代码版本是open JDK-8u 40-src-b25-10 _ feb _ 2015。

传输自分析

那么transferFrom的底层是什么呢? 简单来说,我只是使用了MMAP和堆外内存。

图像

在上面的transferFrom方法代码中,如下所示:

如果是普通文件通道,则使用mmap,否则使用类似于这次使用的SocketChannelImpl的堆外内存。

传输来自mmap详细信息:

图像

简单地说,在一个周期中,每次基于位置将源文件映射到一个mmap,最大为8M,然后顺序地将数据写入目标文件。

传输来自堆外内存详细信息:

图像

从上面的代码可以看出,

如果我们使用的是SocketChannelImpl,我们会在堆外的内存中行走,每次写入的周期最多可达8k。 用完回收,不是释放。

在此,取得堆外存储器方法:

图像

此缓冲区缓存为线程本地,如下图所示,是线程安全的。 类netty内存设计。

图像

请注意,此bufferCache是sun编写的简单版本的基于直接内存的Cache,是一个简单的内存池实现。 内部是数组,默认大小为16。 get方法的key是size。 也就是说,如果数组中的容量超过size,则返回此buffer。

16个源是JVM的基础实现,具体位置: IOUtil.c 140 line。

图像

假设此cache现在有16个插槽,内部现在有14个字节缓冲器。 此时count为14。

图像

start指针指向头部,执行get方法。 此时,从start开始扫描,找到了下标在I的要素。 因为他的capacity比给定的size大。 我们需要提取这个元素。

图像

此时,count需要减1为13,同时将头部的start要素移动到正好空闲的位置。

请注意,必须将start指针放在头部位置。

图像

运行start=(start1) % 16,下次再次获取时,还是从头开始。 你为什么要这么做? 为了避免无谓的遍历,遇到空要素时,直接返回即可。

具体请参照代码:

ByteBuffer bb=buffers[i];

if(bb==null )//避免无谓的循环

布雷克;

用完此ByteBuf后,必须返回————。 如果cache有空的话,是count 16。

怎么还?

有一个返回内存的util.releasetemporarydirectbuffer (bb )方法。 请注意,如果内存池已满,则调用free方法释放内存。

最终调用offerfirsttemporarydirectbuffer方法。

图像

如果添加到缓存池失败,请添加自由、缓存池逻辑:

图像

发行逻辑简单来说就是调用unsafe的自由内存方法

图像

仅限于篇幅,下次再说。 另外,还与一些虚引用的内容有关。

传输从方法总结

如果源类型为FileChannelImpl,请前往mmap,循环映射8MB并将其写入磁盘。

如果源类型为SocketChannelImpl,请在堆外内存中行走。 简单地说,循环放入堆外的存储器中,每8kb擦成磁盘。 注意:这个堆外内存被用来缓存忧郁的大米。 (堆外内存池化是一种常见的优化手段。)。 这种忧郁的大米是数组,长16,使用ThreadLocal提高性能。 每次检索时,如果目标数组小于忧郁的米字节缓冲器容量,则可以使用,如果已使用则可以,如果已满,则调用ui

传输分析

因为transferTo的方法很有趣,所以首先简单地说一下结论:

如果操作系统支持sendfile,请运行系统调用。

如果操作系统不支持,请去mmap。

如果mmap失败,走堆外的内存。

图像

代码如上所示。

注意:如果内核不能运行,则返回-2。 在jvm代码中,我们发现apple、linux、solaris和IBM的AIX都支持send file。

图像

上述代码位置: FileChannelImpl.c 156 line。

如何使用mmap写入网卡? 与transferFrom一样,每次映射最多8Mb的内存并将其打印到网卡上。 每次用完时clean。

私密状态语音地图{

cleanercl=(directbuffer ) bb ).cleaner );

if(cl!=null )

cl.clean (;

}

如何使用直接内存? 与transferFrom一样,每次最多使用8kb,在网卡中放置循环刷。 这里是补助金代码。

总结

查看并总结send file的Java级别实现。 只有transferTo用于send file,而且有条件。 具体如正文第二部分所示。

另一方面,transferFrom方法通常使用mmap或装载外部存储器。 我们似乎有自己能实现的事情,可能反而性能更好。 例如,可以使用更大的缓存而不是多次循环,也可以使用更大的mmap映射而不是8Mb。 每次都需要clean重新映射。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。