<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
零拷貝(英語: Zero-copy)技術是指計算機執行操作時,CPU不需要先將資料從某處記憶體複製到另一個特定區域。這種技術通常用於通過網路傳輸檔案時節省CPU週期和記憶體頻寬。
零拷貝技術可以減少資料拷貝和共用匯流排操作的次數,消除傳輸資料在記憶體之間不必要的中間拷貝次數,從而有效地提高資料傳輸效率。
零拷貝技術減少了使用者程序地址空間和核心地址空間之間因為上下文切換而帶來的開銷。
可以看出沒有說不需要拷貝,只是說減少冗餘不必要的拷貝。
下面這些元件、框架中均使用了零拷貝技術:Kafka、Netty、Rocketmq、Nginx、Apache。
比如:讀取檔案,再用socket傳送出去,實際經過四次copy。
偽碼實現如下:
buffer = File.read() Socket.send(buffer)
四次拷貝的過程:
分析上述的過程,雖然引入DMA來接管CPU的中斷請求,但四次copy是存在“不必要的拷貝”的。實際上並不需要第二個和第三個資料副本。應用程式除了快取資料並將其傳輸回通訊端緩衝區之外什麼都不做。相反,資料可以直接從讀緩衝區傳輸到通訊端緩衝區。
顯然,第二次和第三次資料copy其實在這種場景下沒有什麼幫助反而帶來開銷(DMA拷貝速度一般比CPU拷貝速度快一個數量級),這也正是零拷貝出現的背景和意義。
打個比喻:200M的資料,讀取檔案,再用socket傳送出去,實際經過四次copy(2次cpu拷貝每次100ms ,2次DMA拷貝每次10ms),傳統網路傳輸的話:合計耗時將有220ms。
同時,read和send都屬於系統呼叫,每次呼叫都牽涉到兩次上下文切換:
總結下,傳統的資料傳送所消耗的成本:4次拷貝,4次上下文切換。4次拷貝,其中兩次是DMA copy,兩次是CPU copy。
mmap可以將硬碟上檔案的位置和應用程式緩衝區(application buffers)進行對映(建立一種一一對應關係),將檔案直接對映到使用者空間,所以實際檔案讀取時根據這個對映關係,直接將檔案從硬碟拷貝到使用者空間,只進行了一次資料拷貝,不再有檔案內容從硬碟拷貝到核心空間的一個緩衝區。
mmap記憶體對映將會經歷:3次拷貝: 1次cpu copy,2次DMA copy;
打個比喻:200M的資料,讀取檔案,再用socket傳送出去,如果是使用MMAP實際經過三次copy(1次cpu拷貝每次100ms ,2次DMA拷貝每次10ms),合計只需要120ms。
從資料拷貝的角度上來看,就比傳統的網路傳輸,效能提升了近一倍。
mmap()是在<sys/mman.h>中定義的一個函數,此函數的作用是建立一個新的虛擬記憶體區域,並將指定的物件對映到此區域。mmap其實就是通過記憶體對映的機制來進行檔案操作。
mmap的使用:
import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.StandardCharsets; public class MmapDemo { public static void main(String[] args) throws IOException { File f = new File("/root/map.txt"); RandomAccessFile randomAccessFile = new RandomAccessFile(f, "rw"); FileChannel fileChannel = randomAccessFile.getChannel(); MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, 4096); mappedByteBuffer.put("hello".getBytes(StandardCharsets.UTF_8)); mappedByteBuffer.flip(); byte[] bytes = new byte[5]; mappedByteBuffer.get(bytes, 0, 5); System.out.println("content:" + new String(bytes, StandardCharsets.UTF_8)); } }
使用命令:
strace -ff -o out java MmapDemo
追蹤MmapDemo程式產生的系統呼叫:
openat(AT_FDCWD, "/root/map.txt", O_RDWR|O_CREAT, 0666) = 5 ... ... fstat(5, {st_mode=S_IFREG|0644, st_size=0, ...}) = 0 ftruncate(5, 4096) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_SHARED, 5, 0) = 0x7f9e1c000000
發現底層呼叫了mmap系統呼叫,後續並沒有產生write等系統呼叫,說明資料的讀寫直接發生在了應用態。
另外RocketMQ在原始碼中還使用了FileChannel來做檔案的寫入。
package com.morris.rocketmq.mmap; import java.io.File; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; import java.nio.charset.StandardCharsets; public class FileChannelDemo { public static void main(String[] args) throws IOException { File f = new File("d:\map.txt"); RandomAccessFile randomAccessFile = new RandomAccessFile(f, "rw"); FileChannel fileChannel = randomAccessFile.getChannel(); ByteBuffer byteBuffer = ByteBuffer.allocate(128); byteBuffer.put("hello rocketmq".getBytes(StandardCharsets.UTF_8)); byteBuffer.flip(); fileChannel.write(byteBuffer); fileChannel.close(); } }
為什麼RocketMQ會同時使用FileChannel和MappedByteBuffer在做檔案的寫入,讀取卻只用MappedByteBuffer?
如果按照傳統的方式進行資料傳送,那肯定效能上不去,作為MQ也是這樣,尤其是RocketMQ,要滿足一個高並行的訊息中介軟體,一定要進行優化。所以RocketMQ使用的是MMAP。
RocketMQ原始碼中,使用MappedFile這個類進行MMAP的對映。
這裡需要注意的是,採用MappedByteBuffer這種記憶體對映的方式一次只能對映2G的檔案至使用者態的虛擬記憶體,這也是為何RocketMQ預設設定單個CommitLog紀錄檔資料檔案為1G的原因了。
為什麼是2G?
sun.nio.ch.FileChannelImpl#map
public MappedByteBuffer map(MapMode mode, long position, long size) throws IOException { if (size > Integer.MAX_VALUE) throw new IllegalArgumentException("Size exceeds Integer.MAX_VALUE");
雖然size是long型別,但是限制了size只能是int的最大值,也就是2G。
mmap在原始碼MappedFile中的使用:
public MappedFile(final String fileName, final int fileSize) throws IOException { init(fileName, fileSize); } private void init(final String fileName, final int fileSize) throws IOException { this.fileName = fileName; this.fileSize = fileSize; this.file = new File(fileName); this.fileFromOffset = Long.parseLong(this.file.getName()); boolean ok = false; ensureDirOK(this.file.getParent()); try { this.fileChannel = new RandomAccessFile(this.file, "rw").getChannel(); this.mappedByteBuffer = this.fileChannel.map(MapMode.READ_WRITE, 0, fileSize); TOTAL_MAPPED_VIRTUAL_MEMORY.addAndGet(fileSize); TOTAL_MAPPED_FILES.incrementAndGet(); ok = true; } catch (FileNotFoundException e) { log.error("Failed to create file " + this.fileName, e); throw e; } catch (IOException e) { log.error("Failed to map file " + this.fileName, e); throw e; } finally { if (!ok && this.fileChannel != null) { this.fileChannel.close(); } } }
到此這篇關於MMAP零拷貝在RocketMQ中的運用的文章就介紹到這了,更多相關MMAP RocketMQ運用內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45