3

Golang标准库的读写文件,没有开启用户空间文件缓冲区?

 3 years ago
source link: http://vearne.cc/archives/709
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Golang标准库的读写文件,没有开启用户空间文件缓冲区?

版权声明 本站原创文章 由 萌叔 发表
转载请注明 萌叔 | http://vearne.cc

大家都知道写文件时数据流转的顺序是

用户空间文件缓冲区 -> 内核空间文件缓冲区 -> 内核空间IO队列

29075379_138130814277tC.jpg-63.6kB

默认的ANSI C库,对用户空间文件缓冲区有三种方式

难道Golang没有?笔者不敢断定,但有以下的对比试验或许能说明些问题
write.go

package main

import (
    "os"
    "log"
    "time"
)

func main() {
    file, err := os.OpenFile("test.txt",
        os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0666)
    if err != nil {
        log.Fatal(err)
    }
    for i := 0; i < 1000; i++ {
        time.Sleep(2 * time.Second)
        file.Write([]byte("xxxx"))
    }
    file.Close()
}

write2.go
write2.go 使用了标准库提供的bufio, 给写文件增加了4096byte的缓冲区

package main

import (
    "os"
    "log"
    "time"
    "bufio"
)


func main(){
    file, err := os.OpenFile("test.txt",
        os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0666)
    writer := bufio.NewWriterSize(file, 4096)
    if err!= nil{
        log.Fatal(err)
    }
    for i:=0;i<1000;i++{
        time.Sleep(2 * time.Second)
        writer.Write([]byte("xxxx"))
    }
    writer.Flush()
    file.Close()
}

使用strace跟踪系统调用, 在没有使用bufio的情况如下

) = -1 ETIMEDOUT (Connection timed out)
futex(0x53a1d0, FUTEX_WAKE, 1)          = 1
futex(0xc420072148, FUTEX_WAKE, 1)      = 1
write(3, "xxxx", 4)                     = 4
futex(0x53cb00, FUTEX_WAIT, 0, {1, 999998648}


) = -1 ETIMEDOUT (Connection timed out)
futex(0x53a1d0, FUTEX_WAKE, 1)          = 1
futex(0xc420046948, FUTEX_WAKE, 1)      = 1
write(3, "xxxx", 4)                     = 4
futex(0xc420046948, FUTEX_WAKE, 1)      = 1
futex(0x53cb80, FUTEX_WAIT, 0, {1, 999933913}

每次调用writer.Write([]byte(“xxxx”)) 均有系统调用write(3, “xxxx”, 4) 被触发

使用bufio的情况如下

) = -1 ETIMEDOUT (Connection timed out)
futex(0x53c290, FUTEX_WAKE, 1)          = 1
futex(0xc42006a148, FUTEX_WAKE, 1)      = 1
futex(0x53ebc0, FUTEX_WAIT, 0, {2, 112782}

) = -1 ETIMEDOUT (Connection timed out)
futex(0x53c290, FUTEX_WAKE, 1)          = 1
futex(0xc42006a148, FUTEX_WAKE, 1)      = 1
futex(0xc42006a148, FUTEX_WAKE, 1)      = 1
futex(0x53eb40, FUTEX_WAIT, 0, {1, 999998437}

在用户空间的文件写缓冲区没有写满前,没有write()系统调用被触发,可见使用用户空间文件缓冲区是有效的。

系统调用的开销很高,如果能减少一部分系统调用能够有效的提高服务的吞吐能力。看来以后再读写文件时,很有必要多使用bufio开启用户空间的文件读写缓冲区。

  1. golang中bufio包的实现原理

如果我的文章对你有帮助,你可以给我打赏以促使我拿出更多的时间和精力来分享我的经验和思考总结。

微信支付码

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK