非同步日誌 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
相關文章
- C# .Net 多程式同步 通訊 共享記憶體 記憶體對映檔案 Memory MappedC#記憶體APP
- VC++中用記憶體對映檔案 (轉)C++記憶體
- 二進位制檔案記憶體對映記憶體
- 記憶體對映檔案詳解-----C++實現(即一塊記憶體和一個檔案相對映對應)記憶體C++
- windows核心程式設計--記憶體對映檔案Windows程式設計記憶體
- Python mmap的使用-檔案記憶體對映Python記憶體
- 居然這就是C++記憶體對映檔案?!C++記憶體
- 記憶體對映記憶體
- mmap記憶體對映記憶體
- 一個記憶體檔案對映使用者類 (轉)記憶體
- Linux 記憶體管理:記憶體對映Linux記憶體
- Java記憶體對映,上G大檔案輕鬆處理Java記憶體
- 溫故之.NET程式間通訊——記憶體對映檔案記憶體
- Java使用記憶體對映實現大檔案的上傳Java記憶體
- JAVA記憶體對映檔案實現多執行緒下載Java記憶體執行緒
- 針對持久記憶體的後寫日誌記憶體
- C#記憶體對映大檔案並使用Marshal解析結構體資訊C#記憶體結構體
- Java 中使用記憶體對映檔案需要考慮的 10 個問題Java記憶體
- 【IPC程式間通訊之三】記憶體對映檔案Mapping FileC程式記憶體APP
- Win 95下記憶體對映檔案的工作原理及使用方法 (轉)記憶體
- 記錄日誌檔案
- 對日誌檔案組和日誌檔案組成員的管理
- 從記憶體對映mmap說開去記憶體
- 非歸檔丟失日誌檔案的恢復
- mongodb釋放記憶體-切換日誌MongoDB記憶體
- Laravel 指定日誌檔案記錄任意日誌Laravel
- 【Oracle日誌】- 日誌檔案重建Oracle
- 日誌檔案
- 非歸檔下日誌檔案丟失的處理辦法
- REDO日誌損壞,非歸檔模式資料檔案恢復模式
- 日誌檔案和歸檔日誌檔案的關係以及如何切換日誌
- 操作日誌記錄(包括輸出至自定義日誌檔案)
- hibernate筆記–實體類對映檔案”*.hbm.xml”詳解筆記XML
- mysql 5.5 中對SLAVE relay-log相關日誌檔案同步的強化MySql
- 刪除日誌檔案組與日誌檔案成員
- 管理日誌檔案
- dump日誌檔案
- APACHE日誌檔案Apache