2017-12-18 3 views
6

다음 코드에서 golang의 bufio를 사용하여 파일에 메시지를 씁니다. 내 디스크 I/O 속도는 약 1000M/s입니다. 이상하게도, 쓰기 파일의 크기가 20G보다 작 으면 쓰기 속도는 초당 약 800M ~ 900M이며 I/O 속도보다 약간 적습니다. 하지만 파일 크기가 21G를 초과하면 쓰기 속도가 초당 약 200M이며 I/O 속도보다 훨씬 빠름을 알았습니다. 나는 왜, 누구가 저를 도울다는 것을 모른다? 고맙습니다.골란에서 디스크 쓰기 성능

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 언어로 다시 테스트합니다. 나는 같은 언어로 결과를 찾는다. 내 테스트 결과는 다음과 같습니다 여기

#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 테스트 결과 쇼 : 다음

./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 코드입니다. 내가 코멘트에 쉬운 읽기 결과를 어떻게 코멘트할지 모르기 때문에 여기에 보여줍니다.

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 표창를 사용하여 내 디스크 속도를 테스트하고, 나는이있어 : 파일 크기가 약 18166M보다 작은 경우 버퍼

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 

그래서 어쩌면 내 프로그램을 writting입니다 바이트. 그 후 프로그램은 디스크에 쓰기 때문에 속도가 느립니다.

+0

아마도 그 시점에서 디스크 버퍼가 포화 되었기 때문입니까? – Flimzy

+0

몇 달 전에 C 언어로'writev' 메서드를 사용하여 유사한 프로세스를 작성했습니다. 쓰기 속도가 디스크 I/O 속도와 거의 동일하다는 것을 알았습니다. 디스크 버퍼와 관련이 없음을 증명할 수 있습니까? –

+0

코드를 프로파일 링하십시오. 귀하가 갖고있는 최고의 희망에 관한 것입니다.성능이 21G 이상으로 떨어지면 프로파일에 무엇인가가 보일 것입니다. 가장 가능성이 높습니다. – Marc

답변

0

는 나는이 질문에 대한 답을 얻을 생각합니다. 내 디스크 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 
3

문제는 재현 할 수 없습니다. 코드에 버그가 있습니다.

디스크 쓰기 시간은 프로그램, 다른 프로그램, 운영 체제, 하드웨어 등 여러 요소의 영향을받을 것으로 예상됩니다.

독립 실행 형 전용 컴퓨터를 부팅하고 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

+0

여기 코드에 주석을 달았습니다. 그러나 어떻게해야할지 모르겠습니다. 그래서 시험 결과를 다시 올렸습니다. 내 속도 테스트에 뭔가 잘못됐다고 생각해. 고맙습니다. –

+0

감사합니다. 나는 대답을 얻었다 고 생각한다. –