为了账号安全,请及时绑定邮箱和手机立即绑定

为什么使用 syscall.O_DIRECT 标志写入文件会使写入文件变慢?

为什么使用 syscall.O_DIRECT 标志写入文件会使写入文件变慢?

Go
HUH函数 2022-12-19 20:00:42
我有一小段代码,名为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,系统调用会一直等待,直到数据完全传输到设备。

呼叫的手册页open

O_DIRECT(自 Linux 2.4.10 起)

尽量减少进出此文件的 I/O 的缓存效应。 通常这会降低性能,但在特殊情况下很有用,例如当应用程序进行自己的缓存时。文件 I/O 直接从用户空间缓冲区完成。O_DIRECT标志本身努力同步传输数据,但不保证O_SYNC数据和必要的元数据被传输。

另请参阅:O_DIRECT 的真正含义是什么?

使用后无需手动释放缓存。缓存被 Linux 内核视为可用的可用内存。如果进程需要缓存占用的内存,内核将在此时刷新/释放缓存。缓存不会“用完”内存。


查看完整回答
反对 回复 2022-12-19
  • 1 回答
  • 0 关注
  • 77 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信