Trong đoạn mã sau, tôi viết thư vào một tệp bằng cách sử dụng bufio trong golang. Tốc độ I/O đĩa của tôi là khoảng 1000M/s. Kỳ lạ thay, khi kích thước của tệp văn bản nhỏ hơn 20G, tốc độ ghi là khoảng 800M ~ 900M mỗi giây, thấp hơn một chút so với tốc độ I/O. Nhưng, khi kích thước tập tin lớn hơn 21G, tôi thấy tốc độ ghi là khoảng 200M mỗi giây, ít hơn nhiều so với tốc độ I/O. Tôi không biết tại sao, ai cũng có thể giúp tôi? Cảm ơn bạn.hiệu năng ghi đĩa trong 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)
}
Tôi nghĩ mình đã hỏi một câu hỏi ngu ngốc. Theo phản hồi của Vorsprung
, tôi hiển thị mã C của mình tại đây. Và tôi kiểm tra lại bằng ngôn ngữ C. Tôi tìm thấy kết quả tương tự với ngôn ngữ đi. Kết quả thử nghiệm của tôi là:
./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
Sau đây là mã C của tôi:
#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;
}
Bây giờ kiểm tra diskio.go kết quả chương trình của tôi ở đây. bởi vì tôi không biết làm thế nào để bình luận một kết quả dễ đọc trong bình luận, tôi trình bày nó ở đây.
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 đến từ https://stackoverflow.com/a/47889346/5616809
Tôi nghĩ rằng tôi nhận được câu trả lời, kết quả xét nghiệm là do lý do đĩa đệm. Tôi đã thử nghiệm tốc độ đĩa của tôi sử dụng hdparm
khen, và tôi nhận điều này:
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
byte Vì vậy, có lẽ chương trình của tôi được ghi chép lại để đệm khi kích thước tập tin là ít hơn khoảng 18166M. Sau đó chương trình được ghi vào đĩa, vì vậy tốc độ của nó chậm hơn.
Có lẽ vì bộ đệm đĩa của bạn bị bão hòa tại thời điểm đó? – Flimzy
Vài tháng trước, tôi đã viết một quá trình tương tự bằng cách sử dụng phương thức 'writev' trong ngôn ngữ C. Tôi thấy tốc độ ghi gần bằng với tốc độ I/O của đĩa. Điều này có thể chứng minh rằng nó không liên quan đến bộ đệm đĩa? –
Tiểu sử mã của bạn, đó là về hy vọng tốt nhất mà bạn có.Nếu hiệu suất giảm xuống ngoài 21G, bạn sẽ thấy điều gì đó trong các cấu hình. Rất có thể tôi sẽ đợi. – Marc