范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

面试被问到零拷贝!你要怎么回答?

  前言I/O概念1.缓冲区2.虚拟内存3.mmap+write方式4.sendfile方式Java零拷贝1.MappedByteBuffer2.DirectByteBuffer3.Channel-to-Channel传输Netty零拷贝其他零拷贝总结前言
  从字面意思理解就是数据不需要来回的拷贝,大大提升了系统的性能;这个词我们也经常在java nio,netty,kafka,RocketMQ等框架中听到,经常作为其提升性能的一大亮点;下面从I/O的几个概念开始,进而在分析零拷贝。I/O概念1.缓冲区
  缓冲区是所有I/O的基础,I/O讲的无非就是把数据移进或移出缓冲区;进程执行I/O操作,就是向操作系统发出请求,让它要么把缓冲区的数据排干(写),要么填充缓冲区(读);下面看一个java进程发起read请求加载数据大致的流程图:
  进程发起read请求之后,内核接收到read请求之后,会先检查内核空间中是否已经存在进程所需要的数据,如果已经存在,则直接把数据copy给进程的缓冲区;如果没有内核随即向磁盘控制器发出命令,要求从磁盘读取数据,磁盘控制器把数据直接写入内核read缓冲区,这一步通过DMA完成;接下来就是内核将数据copy到进程的缓冲区;如果进程发起write请求,同样需要把用户缓冲区里面的数据copy到内核的socket缓冲区里面,然后再通过DMA把数据copy到网卡中,发送出去;你可能觉得这样挺浪费空间的,每次都需要把内核空间的数据拷贝到用户空间中,所以零拷贝的出现就是为了解决这种问题的;关于零拷贝提供了两种方式分别是:mmap+write方式,sendfile方式;2.虚拟内存
  所有现代操作系统都使用虚拟内存,使用虚拟的地址取代物理地址,这样做的好处是:1.一个以上的虚拟地址可以指向同一个物理内存地址, 2.虚拟内存空间可大于实际可用的物理地址;利用第一条特性可以把内核空间地址和用户空间的虚拟地址映射到同一个物理地址,这样DMA就可以填充对内核和用户空间进程同时可见的缓冲区了,大致如下图所示:
  省去了内核与用户空间的往来拷贝,java也利用操作系统的此特性来提升性能,下面重点看看java对零拷贝都有哪些支持。3.mmap+write方式
  使用mmap+write方式代替原来的read+write方式,mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系;这样就可以省掉原来内核read缓冲区copy数据到用户缓冲区,但是还是需要内核read缓冲区将数据copy到内核socket缓冲区,大致如下图所示:
  4.sendfile方式
  sendfile系统调用在内核版本2.1中被引入,目的是简化通过网络在两个通道之间进行的数据传输过程。sendfile系统调用的引入,不仅减少了数据复制,还减少了上下文切换的次数,大致如下图所示:
  数据传送只发生在内核空间,所以减少了一次上下文切换;但是还是存在一次copy,能不能把这一次copy也省略掉,Linux2.4内核中做了改进,将Kernel buffer中对应的数据描述信息(内存地址,偏移量)记录到相应的socket缓冲区当中,这样连内核空间中的一次cpu copy也省掉了;Java零拷贝1.MappedByteBuffer
  java nio提供的FileChannel提供了map()方法,该方法可以在一个打开的文件和MappedByteBuffer之间建立一个虚拟内存映射,MappedByteBuffer继承于ByteBuffer,类似于一个基于内存的缓冲区,只不过该对象的数据元素存储在磁盘的一个文件中;调用get()方法会从磁盘中获取数据,此数据反映该文件当前的内容,调用put()方法会更新磁盘上的文件,并且对文件做的修改对其他阅读者也是可见的;下面看一个简单的读取实例,然后在对MappedByteBuffer进行分析:public class MappedByteBufferTest {      public static void main(String[] args) throws Exception {         File file = new File("D://db.txt");         long len = file.length();         byte[] ds = new byte[(int) len];         MappedByteBuffer mappedByteBuffer = new FileInputStream(file).getChannel().map(FileChannel.MapMode.READ_ONLY, 0,                 len);         for (int offset = 0; offset < len; offset++) {             byte b = mappedByteBuffer.get();             ds[offset] = b;         }         Scanner scan = new Scanner(new ByteArrayInputStream(ds)).useDelimiter(" ");         while (scan.hasNext()) {             System.out.print(scan.next() + " ");         }     } }
  主要通过FileChannel提供的map()来实现映射,map()方法如下:    public abstract MappedByteBuffer map(MapMode mode,                                          long position, long size)         throws IOException;
  分别提供了三个参数,MapMode,Position和size;分别表示:MapMode:映射的模式,可选项包括:READ_ONLY,READ_WRITE,PRIVATE;Position:从哪个位置开始映射,字节数的位置;Size:从position开始向后多少个字节;
  重点看一下MapMode,请两个分别表示只读和可读可写,当然请求的映射模式受到Filechannel对象的访问权限限制,如果在一个没有读权限的文件上启用READ_ONLY,将抛出NonReadableChannelException;PRIVATE模式表示写时拷贝的映射,意味着通过put()方法所做的任何修改都会导致产生一个私有的数据拷贝并且该拷贝中的数据只有MappedByteBuffer实例可以看到;该过程不会对底层文件做任何修改,而且一旦缓冲区被施以垃圾收集动作(garbage collected),那些修改都会丢失;大致浏览一下map()方法的源码:    public MappedByteBuffer map(MapMode mode, long position, long size)         throws IOException     {             ...省略...             int pagePosition = (int)(position % allocationGranularity);             long mapPosition = position - pagePosition;             long mapSize = size + pagePosition;             try {                 // If no exception was thrown from map0, the address is valid                 addr = map0(imode, mapPosition, mapSize);             } catch (OutOfMemoryError x) {                 // An OutOfMemoryError may indicate that we"ve exhausted memory                 // so force gc and re-attempt map                 System.gc();                 try {                     Thread.sleep(100);                 } catch (InterruptedException y) {                     Thread.currentThread().interrupt();                 }                 try {                     addr = map0(imode, mapPosition, mapSize);                 } catch (OutOfMemoryError y) {                     // After a second OOME, fail                     throw new IOException("Map failed", y);                 }             }              // On Windows, and potentially other platforms, we need an open             // file descriptor for some mapping operations.             FileDescriptor mfd;             try {                 mfd = nd.duplicateForMapping(fd);             } catch (IOException ioe) {                 unmap0(addr, mapSize);                 throw ioe;             }              assert (IOStatus.checkAll(addr));             assert (addr % allocationGranularity == 0);             int isize = (int)size;             Unmapper um = new Unmapper(addr, mapSize, isize, mfd);             if ((!writable) || (imode == MAP_RO)) {                 return Util.newMappedByteBufferR(isize,                                                  addr + pagePosition,                                                  mfd,                                                  um);             } else {                 return Util.newMappedByteBuffer(isize,                                                 addr + pagePosition,                                                 mfd,                                                 um);             }      }
  大致意思就是通过native方法获取内存映射的地址,如果失败,手动gc再次映射;最后通过内存映射的地址实例化出MappedByteBuffer,MappedByteBuffer本身是一个抽象类,其实这里真正实例化出来的是DirectByteBuffer;2.DirectByteBuffer
  DirectByteBuffer继承于MappedByteBuffer,从名字就可以猜测出开辟了一段直接的内存,并不会占用jvm的内存空间;上一节中通过Filechannel映射出的MappedByteBuffer其实际也是DirectByteBuffer,当然除了这种方式,也可以手动开辟一段空间:ByteBuffer directByteBuffer = ByteBuffer.allocateDirect(100);
  如上开辟了100字节的直接内存空间;3.Channel-to-Channel传输
  经常需要从一个位置将文件传输到另外一个位置,FileChannel提供了transferTo()方法用来提高传输的效率,首先看一个简单的实例:public class ChannelTransfer {     public static void main(String[] argv) throws Exception {         String files[]=new String[1];         files[0]="D://db.txt";         catFiles(Channels.newChannel(System.out), files);     }      private static void catFiles(WritableByteChannel target, String[] files)             throws Exception {         for (int i = 0; i < files.length; i++) {             FileInputStream fis = new FileInputStream(files[i]);             FileChannel channel = fis.getChannel();             channel.transferTo(0, channel.size(), target);             channel.close();             fis.close();         }     } }
  通过FileChannel的transferTo()方法将文件数据传输到System.out通道,接口定义如下:    public abstract long transferTo(long position, long count,                                     WritableByteChannel target)         throws IOException;
  几个参数也比较好理解,分别是开始传输的位置,传输的字节数,以及目标通道;transferTo()允许将一个通道交叉连接到另一个通道,而不需要一个中间缓冲区来传递数据;注:这里不需要中间缓冲区有两层意思:第一层不需要用户空间缓冲区来拷贝内核缓冲区,另外一层两个通道都有自己的内核缓冲区,两个内核缓冲区也可以做到无需拷贝数据;Netty零拷贝
  netty提供了零拷贝的buffer,在传输数据时,最终处理的数据会需要对单个传输的报文,进行组合和拆分,Nio原生的ByteBuffer无法做到,netty通过提供的Composite(组合)和Slice(拆分)两种buffer来实现零拷贝;看下面一张图会比较清晰:
  TCP层HTTP报文被分成了两个ChannelBuffer,这两个Buffer对我们上层的逻辑(HTTP处理)是没有意义的。但是两个ChannelBuffer被组合起来,就成为了一个有意义的HTTP报文,这个报文对应的ChannelBuffer,才是能称之为"Message"的东西,这里用到了一个词"Virtual Buffer"。可以看一下netty提供的CompositeChannelBuffer源码:public class CompositeChannelBuffer extends AbstractChannelBuffer {      private final ByteOrder order;     private ChannelBuffer[] components;     private int[] indices;     private int lastAccessedComponentId;     private final boolean gathering;      public byte getByte(int index) {         int componentId = componentId(index);         return components[componentId].getByte(index - indices[componentId]);     }     ...省略...
  components用来保存的就是所有接收到的buffer,indices记录每个buffer的起始位置,lastAccessedComponentId记录上一次访问的ComponentId;CompositeChannelBuffer并不会开辟新的内存并直接复制所有ChannelBuffer内容,而是直接保存了所有ChannelBuffer的引用,并在子ChannelBuffer里进行读写,实现了零拷贝。其他零拷贝
  RocketMQ的消息采用顺序写到commitlog文件,然后利用consume queue文件作为索引;RocketMQ采用零拷贝mmap+write的方式来回应Consumer的请求;同样kafka中存在大量的网络数据持久化到磁盘和磁盘文件通过网络发送的过程,kafka使用了sendfile零拷贝方式;总结
  零拷贝如果简单用java里面对象的概率来理解的话,其实就是使用的都是对象的引用,每个引用对象的地方对其改变就都能改变此对象,永远只存在一份对象。

微信可以更改信息提示音啦前不久大家都知道微信又有更新了,从微信版本8。0。8开始,ios系统版本的微信更新后可以更改信息提示音和语音来电提示音,接下来跟着小编一起学习如何更改吧!首先我们先打开微信,点击我iOS14。4,苹果进一步加入非原装配件封杀大权在昨日,苹果推出了最新的iOS14。4第二个测试版本Beta2。但是从目前更新后的体验来看,此次14。4B2版本并没有增加任何新的功能,尽管官方宣称修复了更多的Bug以及提升了系统搭载骁龙888的华为P50终于来了,全系没有5G,售价4488起就在昨晚,万众期待的华为P50终于发布了,相信华为P50不少用户已经期待了很久,那么我们直接来看此次华为P50的配置吧!机型此次华为P50的发布相较于以往的P40或者Mate系列而iOS14。5准正式版到来,支持戴口罩解锁,修复续航绿屏等we问题iOS14。5RC版本更新内容预览今天苹果举行了2021年一场春季发布会,本次不光发布AirTag新款AppleTV全新设计M1的iMaciPadPro2021。还有我们期待已久iiOS14。5beta2改善iPhone12绿屏问题iOS14。5beta2体验分享哈喽,各位!欢迎收看本期的iOS系统体验分享。今天是大年初六,追追在这里祝福各位新的一年身体健康万事如意!今天凌晨苹果发布了iOS14。5beta2iOS14。5beta4更新,修复Magsafe正式版下周来iOS14。5beta4体验分享哈喽,各位!欢迎收看本期的iOS系统体验分享。今天凌晨苹果发布了iOS14。5beta4版本,本次更新包大小为383。3MB,版本号为14。5betiOS14。3正式版体验分享,更好拍照5G和续航iOS14。3iPadOS14。3正式版体验分享今天凌晨意料之中苹果发布了iOS14。3iPad14。3正式版系统,本次系统版本号iOS14。3(18C66)与iOS14。3RC2iOS14。5正式版来了,5G续航戴口罩解锁等20项更新iOS14。5正式版体验分享嗨喽,各位!欢迎收看本期的iOS系统体验测试报告,我是追卜忆。今天凌晨苹果发布iOS14。5正式版操作系统,从二月份就开始更新的iOS14。5,历经9个亿色20W充电器体验分享亿色20W充电器体验分享随着科技的进步,智能手机在我们生活中扮演的角色越来越重要。尤其是在4G时代到来之后,我们对于手机的依赖程度就越来越高。手机的续航就是我们尤为看中的一个点。现iOS14。3RC2版本到来,绿屏问题有所改善,续航较好iOS14。3RC2体验分享欢迎各位收看本期的iOS系统更新体验分享。距离上个iOS14RC版本发布三天,苹果又推送了一个iOS14RC的第二个版本。更新包大小与上个版本基本相同,iOS15正式版体来袭,还没更新的小伙伴都来看看吧iOS15正式版体2021年9月21日,苹果正式向所有用户推送了iOS15正式版操作系统。还有iPadOS15watchOS8。0。有多少小伙伴已经忍不住更新了?还没有更新的小伙们
手机设置一下到哪里都能自动连接WiFi,操作方法简单,零基础可学嗨,大家好,我是大海,欢迎大家来欣赏我的文章,我每天给大家分享手机实用技巧,现在是网络时代,信息时代,每个人都离不开手机,无论是哪一种生活方式的人,每一个阶段的人来说都是非常重要的美国开始恢复芯片供应,但华为并不买账,网友霸气众所周知,近年来老美对于华为的打击是全方位且歇斯底里的,别说芯片了,就连一颗老美造的零配件,没得到允许,华为都买不着。但令人感到惊讶的是,老美从今年6月开始,逐渐放开了芯片限制,高目前大家公认的真香手机,这5部手机值得考虑,三五年不过时说到未来几年不过时的手机,那肯定要考虑最近发布的,还有就是硬件配置强,堆料猛的机型。讲实话,市面上还真有不少值得考虑的手机,你不妨看一下!目前大家公认的真香手机,这5部手机值得考虑百度造车公布最新进展集度已开展模拟样车智能驾驶开发9月24日,集度CEO夏一平宣布,集度成立207天,软件团队已基于SIMUCar(模拟样车)与百度Apollo团队协作智能座舱以及智能驾驶功能的开发。夏一平在微博中公布了集度和Ap小米造汽车,吉利造手机?内卷这么严重了吗24日,多方消息传出吉利汽车正在筹备手机业务,项目进展十分迅速,已经开始在业内寻觅人才,公司将在湖北武汉上海等多地,乃至海外设置办公地点。对此,吉利官方也迅速做出回复目前没有可以对为啥说经济差的城市饭馆多,混得差的男人关心政治?谬论!按你说的北上广不能开饭店,西方发达国家就没人关心国家大事了,这样一派胡言也敢拿在头条提问?你应先去托儿所问一下阿姨去吧。关心政治的并非混的差,相反有雄心大志的人才更关心政治。边缘计算对于下一阶段智慧城市规划的意义如果边缘计算能力可以融入我们城市的结构,这可能会彻底改变我们与他们互动的方式。在过去的十年中,许多城市推出了庞大(且成本高昂)的智慧城市计划。在这种转变的早期,重点是数据的收集和集负面消息接连发生,为何特斯拉Model3越卖越火?当2012年4月22日,特斯拉带着首款车型ModelS进入中国之时,由于其纯电驱动的动力设计,加上当时高昂的售价,并没有引起广泛的关注。然而随着电动智能化发展,越来越多的新能源车企AI药物研发赛道火热BAT之后华为强势跨界入局来源21世纪经济报道提到人工智能时,大多数人想到的是科幻小说中有知觉的智能机器人,现代科学虽然尚未破解这种机器人的奥妙,但是却发现了AI技术可以应用于新药研发领域。近日,华为发布了朝媒朝鲜研发出七语种AI翻译器,英中日翻译准确率可达专家水平韩联社10月3日报道,据朝鲜外宣媒体今日朝鲜3日报道,金日成综合大学信息科学部人工智能技术研究所日前研发出朝鲜式的机器翻译服务系统龙马,并将其广泛投入使用。据悉,该翻译程序可实现与现在的手机双卡双待,为什么很多人开始用两个手机?用两部手机,可以区别使用功能。可以选择配置不同,实现高低兼顾。可以选用不同品牌手机,各取所长。安全性高,假如丢一个,不会立即出现无机可用的尴尬局面。因为用的卡都是一个公司的,双卡双