我有一小段代碼,名為test.go. 它在執行兩次寫入時計算時間(ns),將相同的字節片寫入 2 個文件,一個帶有標志syscall.O_DIRECT,另一個沒有。代碼如下:package main;import ( "os" "time" "fmt" "strconv" "bytes" "syscall" // "os/exec")func main() { num, _ := strconv.Atoi(os.Args[1]); writeContent:= bytes.Repeat( ([]byte)("1"), num ); t1:= time.Now().UnixNano(); fd1, err := syscall.Open("abc.txt", syscall.O_WRONLY | syscall.O_DIRECT | syscall.O_TRUNC, 0); syscall.Write(fd1, writeContent); if err != nil {panic(err);} t2:= time.Now().UnixNano(); fmt.Println("sysW1:", t2-t1); t1= time.Now().UnixNano(); fd2, err := syscall.Open("abc.txt", syscall.O_WRONLY | syscall.O_TRUNC, 0); syscall.Write(fd2, writeContent); if err != nil {panic(err);} t2= time.Now().UnixNano(); fmt.Println("sysW2:", t2-t1);}該程序在 linux 命令行中運行,如下所示:(編譯后go build ./test.go)./test 1024我原以為寫有標志syscall.O_DIRECT的文件會更快,但結果表明寫有syscall.O_DIRECT標志的文件比沒有它的寫慢大約30倍:(結果:sysW1: 1107377sysW2: 37155為什么?我認為使用 syscall.O_DIRECT 進行編寫會減少復制并且會更快,但現在證明它要慢得多。請幫我解釋一下:(PX:我不會提供游樂場鏈接,因為在游樂場運行程序時由于某些原因總是返回0。
1 回答

白衣染霜花
TA貢獻1796條經驗 獲得超10個贊
O_DIRECT
沒有按照你的想法去做。雖然它減少了內存復制(因為它不會在復制到設備驅動程序之前復制到緩存),但這并不能提高性能。
文件系統緩存確保系統調用可以在數據寫入設備之前盡早返回,并緩沖數據以更大的塊發送數據。
使用O_DIRECT
,系統調用會一直等待,直到數據完全傳輸到設備。
O_DIRECT
(自 Linux 2.4.10 起)盡量減少進出此文件的 I/O 的緩存效應。 通常這會降低性能,但在特殊情況下很有用,例如當應用程序進行自己的緩存時。文件 I/O 直接從用戶空間緩沖區完成。
O_DIRECT
標志本身努力同步傳輸數據,但不保證O_SYNC
數據和必要的元數據被傳輸。
另請參閱:O_DIRECT 的真正含義是什么?
使用后無需手動釋放緩存。緩存被 Linux 內核視為可用的可用內存。如果進程需要緩存占用的內存,內核將在此時刷新/釋放緩存。緩存不會“用完”內存。
- 1 回答
- 0 關注
- 145 瀏覽
添加回答
舉報
0/150
提交
取消