golang的磁盘写入性能

在以下代码中,我使用golang中的bufio将消息写入文件。我的磁盘I/O速度约为1000M/s。奇怪的是,当写入文件的大小小于20G时,写入速度大约为800M〜900M每秒,比I/O速度略低一点。但是,当文件大小超过21G时,我发现写入速度大约为每秒200M,远远低于I/O速度。我不知道为什么,有人可以帮助我?谢谢。golang的磁盘写入性能

package main 

import "fmt"

import (

"os"

"time"

"flag"

"bufio"

)

func main() {

var pRound = flag.Int64("round", 3500000, "loop round")

flag.Parse()

var message string

for i := 0; i < 1024; i++ {

message += "1234567890"

}

message += "\n"

f, err := os.OpenFile("server", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0666)

if err != nil {

fmt.Println(err)

return

}

w := bufio.NewWriter(f)

var i int64 = 0

round := *pRound

start := time.Now()

for i = 0; i < round; i++ {

w.WriteString(message)

}

w.Flush()

f.Close()

end := time.Now()

nanoseconds := end.Sub(start).Nanoseconds()

speed := 1000000000 * round/nanoseconds

fmt.Printf("round: %v\n", round)

fmt.Printf("Nanoseconds: %v\n", nanoseconds)

fmt.Printf("speed: %v\n", speed)

}

我想我已经问过一个愚蠢的问题。关于Vorsprung的回应,我在这里展示了我的C代码。我用C语言再次测试它。我用go语言找到了相同的结果。我的测试结果是:

./a.out 10000 

seconds: 7

milliseconds: 260910

total: 10485760000 Bytes

total: 10000 M

total: 9.76562 G

speed: 1377.24 M/s

./a.out 20000

seconds: 24

milliseconds: 7249

total: 20971520000 Bytes

total: 20000 M

total: 19.5312 G

speed: 833.082 M/s

./a.out 30000

seconds: 80

milliseconds: 518970

total: 31457280000 Bytes

total: 30000 M

total: 29.2969 G

speed: 372.583 M/s

./a.out 40000

seconds: 134

milliseconds: 615910

total: 41943040000 Bytes

total: 40000 M

total: 39.0625 G

speed: 297.142 M/s

以下是我的C代码:

#include <fcntl.h> 

#include <errno.h>

#include <limits.h>

#include <sys/uio.h>

#include <time.h>

#include <sys/time.h>

#include <iostream>

#include <string.h>

#include <stdlib.h>

int main(int argc, char* argv[]) {

if (argc != 2) {

std::cout << "usage: " << argv[0] << " round" << std::endl;

return -1;

}

int round = atoi(argv[1]);

int fd = open("file.data", O_CREAT | O_APPEND | O_RDWR, 0666);

if (fd == -1) {

std::cout << "open file error: " << strerror(errno) << std::endl;

return -1;

}

struct iovec vec[IOV_MAX];

int len = 1024;

for (int i = 0; i < IOV_MAX; i++) {

vec[i].iov_base = new char[len];

vec[i].iov_len = len;

char *buf = NULL;

for (int j = 0; j < len - 1; j++) {

buf = (char*)vec[i].iov_base;

buf[j] = j % 10 + '1';

}

buf[len - 1] = '\n';

}

timeval tv1;

gettimeofday(&tv1, NULL);

for (int i = 0; i < round; i++) {

writev(fd, vec, IOV_MAX);

}

close(fd);

timeval tv2;

gettimeofday(&tv2, NULL);

for (int i = 0; i < IOV_MAX; i++) {

char* buf = (char*)vec[i].iov_base;

delete[] buf;

}

std::cout << "seconds: " << tv2.tv_sec - tv1.tv_sec << std::endl;

std::cout << "milliseconds: " << tv2.tv_usec - tv1.tv_usec << std::endl;

int64_t total = int64_t(len) * IOV_MAX * round;

float t = (tv2.tv_sec - tv1.tv_sec) * 1000000.0 + (tv2.tv_usec - tv1.tv_usec);

float speed = 1000000.0 * total/t/1024/1024;

std::cout << "total: " << total << " Bytes" << std::endl;

std::cout << "total: " << total/1024.0/1024.0 << " M" << std::endl;

std::cout << "total: " << total/1024.0/1024.0/1024.0 << " G" << std::endl;

std::cout << "speed: " << speed << " M/s" << std::endl;

return 0;

}

现在我diskio.go测试结果显示在这里。因为我不知道如何评论简单阅读的结果,所以我在这里展示它。

time ./diskio -size=4 

written: 4294967296B 26237051975ns 4.29GB 26.24s 163.70MB/s

real 0m26.980s

user 0m0.397s

sys 0m4.874s

time ./diskio -size=8

written: 8589934592B 57803019028ns 8.59GB 57.80s 148.61MB/s

real 0m59.192s

user 0m0.813s

sys 0m9.607s

time ./diskio -size=10

written: 10737418240B 68331989999ns 10.74GB 68.33s 157.14MB/s

real 1m10.288s

user 0m0.946s

sys 0m12.024s

time ./diskio -size=20

written: 21474836480B 141169506440ns 21.47GB 141.17s 152.12MB/s

real 2m25.037s

user 0m1.881s

sys 0m24.029s

time ./diskio -size=30

written: 32212254720B 203807569664ns 32.21GB 203.81s 158.05MB/s

real 3m29.345s

user 0m2.925s

sys 0m33.528s

diskio.go来自https://stackoverflow.com/a/47889346/5616809

我觉得我得到了答案,测试结果由磁盘缓冲区的原因造成的。我测试了我的硬盘速度使用hdparm表彰,而我得到这个:

hdparm -Tt /dev/sde1 

/dev/sde1:

Timing cached reads: 18166 MB in 2.00 seconds = 9093.93 MB/sec

Timing buffered disk reads: 584 MB in 3.01 seconds = 194.18 MB/sec

所以,也许我的程序书面方式字节缓冲区时,文件大小小于约18166M。之后,该程序正在写入磁盘,所以速度较慢。

回答:

我觉得我得到的回答这个问题。由于我的磁盘I/O速度约为194M/s,磁盘缓冲I/O约为9093M/s。但磁盘缓冲区大小约为18166M。所以当文件大小小于20G时写入速度会更快。我用这个命令来测试我的磁盘I/O速度:

hdparm -Tt /dev/sde1 

/dev/sde1:

Timing cached reads: 18166 MB in 2.00 seconds = 9093.93 MB/sec

Timing buffered disk reads: 584 MB in 3.01 seconds = 194.18 MB/sec

回答:

您的问题是无法重复的。你的代码有错误。

我们预计磁盘写入时间会受到很多因素的影响:程序,其他程序,操作系统,硬件等等。

启动独立的专用机器并运行diskio.go程序。你会得到什么结果?例如,我的机器上:

$ go build diskio.go 

$ time ./diskio -size=32

written: 34359738368B 154333936544ns 34.36GB 154.33s 222.63MB/s

real 2m35.323s

user 0m6.418s

sys 0m41.994s

$ time ./diskio -size=16

written: 17179869184B 77901269159ns 17.18GB 77.90s 220.53MB/s

real 1m18.746s

user 0m2.849s

sys 0m21.721s

$ time ./diskio -size=8

written: 8589934592B 38940248134ns 8.59GB 38.94s 220.59MB/s

real 0m39.625s

user 0m1.719s

sys 0m12.493s

$ time ./diskio -size=1

written: 1073741824B 4738082404ns 1.07GB 4.74s 226.62MB/s

real 0m4.851s

user 0m0.069s

sys 0m0.755s

$

正如预期的那样,很少有时间在节目中度过,更多的时间是在操作系统中度过的,大量的时间都花在等待在磁盘上。写入速度没有急剧变化。

diskio.go

package main 

import (

"bufio"

"flag"

"fmt"

"os"

"time"

)

func writeFile(fSize int64) error {

fName := `/home/peter/diskio` // test file

defer os.Remove(fName)

f, err := os.Create(fName)

if err != nil {

return err

}

const defaultBufSize = 4096

buf := make([]byte, defaultBufSize)

buf[len(buf)-1] = '\n'

w := bufio.NewWriterSize(f, len(buf))

start := time.Now()

written := int64(0)

for i := int64(0); i < fSize; i += int64(len(buf)) {

nn, err := w.Write(buf)

written += int64(nn)

if err != nil {

return err

}

}

err = w.Flush()

if err != nil {

return err

}

err = f.Sync()

if err != nil {

return err

}

since := time.Since(start)

err = f.Close()

if err != nil {

return err

}

fmt.Printf("written: %dB %dns %.2fGB %.2fs %.2fMB/s\n",

written, since,

float64(written)/1000000000, float64(since)/float64(time.Second),

(float64(written)/1000000)/(float64(since)/float64(time.Second)),

)

return nil

}

var size = flag.Int("size", 8, "file size in GiB")

func main() {

flag.Parse()

fSize := int64(*size) * (1024 * 1024 * 1024)

err := writeFile(fSize)

if err != nil {

fmt.Fprintln(os.Stderr, fSize, err)

}

}

游乐场:https://play.golang.org/p/vnjnpgMzsV

以上是 golang的磁盘写入性能 的全部内容, 来源链接: utcz.com/qa/261840.html

回到顶部