我有一小段代码,名为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 关注
- 125 浏览
添加回答
举报
0/150
提交
取消