非同步日誌 vs. 記憶體對映檔案
高頻交易 HFT 系統目標是降低I/O延遲,當你寫磁碟或透過網路傳輸不可避免地你將延遲差效能匯入你的系統,一種解決方案是使用NIO (non-blocking I/O). 對於磁碟I/O使用記憶體對映檔案memory-mapped file ,而對於網路I/O 你可以使用非堵塞通道. NIO是一種非同步輸出,意味著你將位元組傳交付給OS (i.e. copy them to a direct byte buffer),希望底層OS能夠做好這部分工作。
下面以日誌記錄為案例:
先樹立的一個比較樣本,如果日誌資訊在記憶體中直接複製,大概需要多少時間,用ByteBuffer 帶來的結果:
記憶體中直接複製最短執行時間:
Avg Time: 26.42 nanos
下面引入檔案磁碟系統,比較 記憶體對映檔案和非同步日誌 哪個最快。
1.1MappedByteBuffer記憶體對映檔案帶來的延遲
執行時間:
Avg Time: 53.52 nanos
2. Lock-free Queue 無鎖佇列也就是非同步的延遲:
執行時間:
Avg Time: 30.95 nanos
總結,非同步日誌時間要比使用記憶體對映檔案委託底層OS操作更快。
下面以日誌記錄為案例:
先樹立的一個比較樣本,如果日誌資訊在記憶體中直接複製,大概需要多少時間,用ByteBuffer 帶來的結果:
String msg = "This is a log message not so small that you can use to test. I hope you have fun and it works well!"; byte[] msgBytes = msg.getBytes(); ByteBuffer bb = ByteBuffer.allocate(1024); long start = System.nanoTime(); bb.put(msgBytes); long end = System.nanoTime(); System.out.println("Time: " + (end - start)); <p class="indent"> |
記憶體中直接複製最短執行時間:
Avg Time: 26.42 nanos
下面引入檔案磁碟系統,比較 記憶體對映檔案和非同步日誌 哪個最快。
1.1MappedByteBuffer記憶體對映檔案帶來的延遲
File file = new File("mMapFile.txt"); RandomAccessFile raf = new RandomAccessFile(file, "rw"); MappedByteBuffer mappedBuffer = raf.getChannel().map(MapMode.READ_WRITE, 0, 1024); long start = System.nanoTime(); mappedBuffer.put(msgBytes); long end = System.nanoTime(); System.out.println("Time: " + (end - start)); <p class="indent"> |
執行時間:
Avg Time: 53.52 nanos
2. Lock-free Queue 無鎖佇列也就是非同步的延遲:
Builder<ByteBuffer> builder = new Builder<ByteBuffer>() { @[author]Override[/author] public ByteBuffer newInstance() { // max log message size is 1024 return ByteBuffer.allocate(1024); } }; final BatchingQueue<ByteBuffer> queue = new AtomicQueue<ByteBuffer>(1024 * 1024, builder); final WaitStrategy consumerWaitStrategy = new ParkWaitStrategy(); Thread asyncLogger = new Thread(new Runnable() { @[author]Override[/author] public void run() { while (true) { long avail; while((avail = queue.availableToPoll()) == 0) { consumerWaitStrategy.waitForOtherThread(); } consumerWaitStrategy.reset(); for(int i = 0; i < avail; i++) { ByteBuffer bb = queue.poll(); bb.flip(); if (bb.remaining() == 0) { // EOF return; } else { // log your byte buffer here // any way you want since you // are not disrupting the main // thread anymore... } bb.clear(); } queue.donePolling(); } } }, "AsyncLogger"); asyncLogger.start(); long start = System.nanoTime(); ByteBuffer bb; while((bb = queue.nextToDispatch()) == null) { // busy spin in case queue is full } bb.put(msgBytes); queue.flush(true); // true = lazySet() long end = System.nanoTime(); System.out.println("Time: " + (end - start)); <p class="indent"> |
執行時間:
Avg Time: 30.95 nanos
總結,非同步日誌時間要比使用記憶體對映檔案委託底層OS操作更快。
非同步日誌 vs. 記憶體對映檔案Asynchronous logging versus Memory Mapped Files | MentaBlog
相關文章
- 使用記憶體對映檔案(mmap)記憶體
- 二進位制檔案記憶體對映記憶體
- Python mmap的使用-檔案記憶體對映Python記憶體
- windows核心程式設計--記憶體對映檔案Windows程式設計記憶體
- 居然這就是C++記憶體對映檔案?!C++記憶體
- Java記憶體對映,上G大檔案輕鬆處理Java記憶體
- 溫故之.NET程式間通訊——記憶體對映檔案記憶體
- 針對持久記憶體的後寫日誌記憶體
- C#記憶體對映大檔案並使用Marshal解析結構體資訊C#記憶體結構體
- linux記憶體管理(八)- 反向對映RMAPLinux記憶體
- 從記憶體對映mmap說開去記憶體
- Laravel 指定日誌檔案記錄任意日誌Laravel
- 操作日誌記錄(包括輸出至自定義日誌檔案)
- springboot使用logback記錄日誌,配置檔案Spring Boot
- linux檔案存在記憶體裡Linux記憶體
- WINDOWS下對NIGNX日誌檔案進行限制Windows
- 載入Mapper對映檔案APP
- Mybatis對映檔案簡介MyBatis
- 共享記憶體對映(linux程式與執行緒學習筆記)記憶體Linux執行緒筆記
- SLF4J記錄日誌&&日誌檔案的滾動策略__SpringBootSpring Boot
- 使用配置檔案方式記錄Python程式日誌Python
- MySQL提升筆記(3)日誌檔案詳解MySql筆記
- 【MySQL日誌】MySQL日誌檔案初級管理MySql
- Ubuntu 新增虛擬記憶體檔案Ubuntu記憶體
- 日誌導致jvm記憶體溢位相關問題JVM記憶體溢位
- [非專業翻譯] Mapster - 對映前&對映後
- java專案日誌配置檔案Java
- 記錄一則clear重做日誌檔案的案例
- 檔案同步對比軟體:Beyond Compare 4 for MacMac
- MySQL InnoDB日誌檔案配置MySql
- sybase iq日誌檔案管理
- 日誌檔案過大清理
- Java堆記憶體Heap與非堆記憶體Non-HeapJava記憶體
- 作業系統-記憶體、檔案管理作業系統記憶體
- nginx容器卷對映檔案不生效Nginx
- 記憶體對齊記憶體
- Mybatis 學習筆記(一)——配置檔案SqlMapConfig.xml和對映檔案Mapper.xmlMyBatis筆記SQLXMLAPP
- [外掛擴充套件]非同步除錯神器Slog,“從此告別看日誌,清日誌檔案了”套件非同步除錯
- 手工rm刪除歸檔日誌對備份歸檔日誌的影響