巫溪网站建设,ghost wordpress 比较,石家庄网站怎么建设,500云网站1 PageCache
●由内存中的物理page组成#xff0c;其内容对应磁盘上的block。
●page cache的大小是动态变化的。
●backing store#xff1a;cache缓存的存储设备。
●一个page通常包含多个block,而block不一定是连续的。
1.1读Cache
●当内核发起一个读请求时#x…1 PageCache
●由内存中的物理page组成其内容对应磁盘上的block。
●page cache的大小是动态变化的。
●backing storecache缓存的存储设备。
●一个page通常包含多个block,而block不一定是连续的。
1.1读Cache
●当内核发起一个读请求时先会检查请求的数据是否缓存到了page cache中。
如果有那么直接从内存中读取不需要访问磁盘此即cache hit(缓存命中)
如果没有就必须从磁盘中读取数据,然后内核将读取的数据再缓存到cache中如此后续的读请求就可以命中缓存了。
●page可以只缓存一个文件的部分内容而不需要把整个文件都缓存进来。
1.2写Cache
●当内核发起一个写请求时也是直接往cache中写入后备存储中的内容不会直接更新。
●内核会将被写入的page标记为dirty并将其加入到dirty list中。
●内核会周期性地将dirty list中的page写回到磁盘上从而使磁盘上的数据和内存中缓存的数据一致。
1.3 cache回收
●Page cache的另一个重要工作是释放page从而释放内存空间。
●cache回收的任务是选择合适的page释放
如果page是dirty的需要将page写回到磁盘中再释放。 2 cache和buffer的区别
(1) Cache缓存区是高速缓存是位于CPU和主内存之间的容量较小但速度很快的存储器因为CPU的速度远远高于主内存的速度CPU从内存中读取数据需等待很长的时间而Cache
保存着CPU刚用过的数据或循环使用的部分数据这时从Cache中读取数据会更快减少了CPU等待的时间提高了系统的性能。 Cache并不是缓存文件的而是缓存块的(块是I/O读写最小的单元)Cache一般会用在I/O请求上如果多个进程要访问某个文件可以把此文件读入Cache中这样下一个进程获取CPU控制权并访问此文件直接从Cache读取提高系统性能。 (2)Buffer缓冲区用于存储速度不同步的设备或优先级不同的设备之间传输数据通过buffer可以减少进程间通信需要等待的时间当存储速度快的设备与存储速度慢的设备进行通信时存储慢的数据先把数据存放到buffer达到一定程度存储快的设备再读取buffer的数据在此期间存储快的设备CPU可以干其他的事情。 Buffer一般是用在写入磁盘的例如某个进程要求多个字段被读入当所有要求的字段被读入之前已经读入的字段会先放到buffer中。 3 HeapByteBuffer和DirectByteBuffer
HeapByteBuffer是在jvm堆上面一个buffer底层的本质是一个数组用类封装维护了很多的索引(limit/position/capacity等)。
DirectByteBuffer底层的数据是维护在操作系统的内存中而不是jvm里DirectByteBuffer里维护了一个引用address指向数据进而操作数据。
HeapByteBuffer优点内容维护在jvm里把内容写进buffer里速度快更容易回收。
DirectByteBuffer优点跟外设(I0设备)打交道时会快很多因为外设读取jvm堆里的数据时
不是直接读取的而是把jvm里的数据读到一个内存块里再在这个块里读取的如果使用
DirectByteBuffer则可以省去这一步实现zero copy (零拷贝) 外设之所以要把jvm堆里的数据copy出来再操作不是因为操作系统不能直接操作jvm内存而是因为jvm在进行gc (垃圾回收)时会对数据进行移动一旦出现这种问题外设就会出现数据错乱的情况。 所有的通过allocate方法创建的buffer都是HeapByteBuffer。 堆外内存实现零拷贝
(1)前者分配在JVM堆上(ByteBuffer allocate())后者分配在操作系统物理内存上
(ByteBuffer allocateDirect()JVM使用C库中的malloc()方法分配堆外内存)
(2)DirectByteBuffer可以减少JVM GC压力当然堆中依然保存对象引用fullgc发生时也会回收直接内存也可以通过system.gc主动通知JVM回收或者通过cleaner.clean主动清理。
Cleaner.create()方法需要传入一个DirectByteBuffer对象和一个Deallocator (一个堆外内存回收线程)。GC发生时发现堆中的DirectByteBuffer对象没有强引用了则调用Deallocator的run()方法回收直接内存并释放堆中DirectByteBuffer的对象引用
(3)底层I/O操作需要连续的内存UVM堆内存容易发生GC和对象移动)所以在执行write操作时需要将HeapByteBuffer数据拷贝到一个临时的(操作系统用户态)内存空间中会多一次额外拷贝。而DirectByteBuffer则可以省去这个拷贝动作这是Java层面的“零拷贝”技术在netty中广泛使用
(4)MappedByteBuffer底层使用了操作系统的mmap机制FileChannel#map(方法就会返回MappedByteBuffer。DirectByteBuffer虽然实现了 MappedByteBuffer不过DirectByteBuffer默认并没有直接使用mmap机制。 4缓冲IO和直接IO
4.1缓存IO
缓存I/O又被称作标准I/O大多数文件系统的默认I/O操作都是缓存I/O。在Linux的缓存I/O机制中数据先从磁盘复制到内核空间的缓冲区,然后从内核空间缓冲区复制到应用程序的地址空间。
读操作操作系统检查内核的缓冲区有没有需要的数据如果已经缓存了那么就直接从缓存中返回否则从磁盘中读取然后缓存在操作系统的缓存中。
写操作将数据从用户空间复制到内核空间的缓存中。这时对用户程序来说写操作就已经完成至于什么时候再写到磁盘中由操作系统决定除非显示地调用了sync同步命令。 缓存I/O的优点
(1)在一定程度上分离了内核空间和用户空间保护系统本身的运行安全
(2)可以减少读盘的次数从而提高性能。 缓存I/O的缺点
(1)在缓存I/O机制中DMA方式可以将数据直接从磁盘读到页缓存中或者将数据从页缓存直接写回到磁盘上而不能直接在应用程序地址空间和磁盘之间进行数据传输。数据在传输过程中就需要在应用程序地址空间(用户空间)和缓存(内核空间)之间进行多次数据拷贝操作这些数据拷贝操作所带来的CPU以及内存开销是非常大的。 4.2直接IO
直接IO就是应用程序直接访问磁盘数据而不经过内核缓冲区这样做的目的是减少一次从内核缓冲区到用户程序缓存的数据复制。比如说数据库管理系统这类应用它们更倾向于选择它们自己的缓存机制因为数据库管理系统往往比操作系统更了解数据库中存放的数据数据库管理系统可以提供一种更加有效的缓存机制来提高数据库中数据的存取性能。 直接IO的缺点如果访问的数据不在应用程序缓存中那么每次数据都会直接从磁盘加载这种直接加载会非常缓慢。通常直接IO与异步IO结合使用会得到此较好的性能。 5内存映射文件(Mmap)
在LINUX中我们可以使用mmap用来在进程虚拟内存地址空间中分配地址空间创建和物理内存的映射关系。 映射关系可以分为两种
(1)文件映射磁盘文件映射进程的虚拟地址空间,使用文件内容初始化物理内存。
(2)匿名映射初始化全为0的内存空间。 而对于映射关系是否共享又分为
(1)私有映射(MAP. PRIVATE)多进程间数据共享修改不反应到磁盘实际文件是一个copy-on-write (写时复制)的映射方式。
(2)共享映射(MAP. SHARED)多进程间数据共享修改反应到磁盘实际文件中。 因此总结起来有4种组合
(1)私有文件映射多个进程使用同样的物理内存页进行初始化但是各个进程对内存文件的修改不会共享也不会反应到物理文件中
(2)私有匿名映射mmap会创建一个新的映射各个进程不共享这种使用主要用于分配内存(malloc分配大内存会调用mmap)。例如开辟新进程时会为每个进程分配虚拟的地址空间这些虚拟地址映射的物理内存空间各个进程间读的时候共享写的时候会copy-on-write。
(3)共享文件映射多个进程通过虚拟内存技术共享同样的物理内存空间对内存文件的修改会反应到实际物理文件中他也是进程间通信(IPC)的一种机制。
(4)共享匿名映射这种机制在进行fork的时候不会采用写时复制父子进程完全共享同样的物理内存页这也就实现了父子进程通信(IPC)。 mmap只是在虚拟内存分配了地址空间只有在第一次访问虚拟内存的时候才分配物理内存。
在mmap之后并没有在将文件内容加载到物理页上只上在虚拟内存中分配了地址空间。当进程在访问这段地址时通过查找页表发现虚拟内存对应的页没有在物理内存中缓存则产生缺页由内核的缺页异常处理程序处理将文件对应内容以页为单位(4096)加载到物理内存注意是只加载缺页但也会受操作系统一些调度策略影响加载的比所需的多。 6直接内存读取并发送文件的过程 7 Mmap读取并发送文件的过程 8 Sendfile零拷贝读取并发送文件的过程 零拷贝(zero copy)小结
(1)虽然叫零拷贝实际上sendfile有2次数据拷贝的。第1次是从磁盘拷贝到内核缓冲区第二次是从内核缓冲区拷贝到网卡(协议引擎)。如果网卡支持SG-DMA (The Scatter-Gather Direct Memory Access)技术就无需从PageCache拷贝至Socket缓冲区
(2)之所以叫零拷贝是从内存角度来看的数据在内存中没有发生过拷贝只是在内存和I/O设备之间传输。很多时候我们认为sendfile才是零拷贝mmap严格来说不算
(3)Linux中的API为sendfile、mmapJava中的API为FileChanel.transferTo().FileChannel.map()等
(4)Netty、Kafka(sendfile)、Rocketmq (mmap)、Nginx等高性能中间件中都有大量利用操作系统零拷贝特性。