2017-12-18 92 views
6

में डिस्क लेखन प्रदर्शन निम्नलिखित कोड में, मैं गोल्फ में bufio का उपयोग कर फ़ाइल में संदेश लिखता हूं। मेरी डिस्क I/O गति लगभग 1000 एम/एस है। आश्चर्यजनक रूप से, जब लिखित फ़ाइल का आकार 20 जी से कम है, तो लिखने की गति लगभग 800 एम ~ 900 एम प्रति सेकंड है, I/O गति से थोड़ा कम है। लेकिन, जब फ़ाइल का आकार 21 जी से अधिक है, तो मुझे लगता है कि लेखन गति प्रति सेकंड लगभग 200 मीटर है, 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 की प्रतिक्रिया पर, मैं यहां अपना सी कोड दिखाता हूं। और मैं फिर से सी भाषा में इसका परीक्षण करता हूं। मुझे जाने वाली भाषा के साथ एक ही परिणाम मिलते हैं। मेरा परीक्षण परिणाम है:

#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 

निम्नलिखित मेरी सी कोड है। क्योंकि मुझे नहीं पता कि टिप्पणी में आसान पढ़ने के परिणाम को कैसे टिप्पणी करें, मैं इसे यहां दिखाता हूं।

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

कई महीने पहले, मैंने सी भाषा में 'writev' विधि का उपयोग करके एक समान प्रक्रिया लिखी थी। मैंने पाया कि लेखन की गति लगभग डिस्क I/O गति के बराबर है। क्या यह साबित कर सकता है कि यह डिस्क बफर से संबंधित नहीं है? –

+0

अपना कोड प्रोफाइल करें, जो आपके पास सबसे अच्छी आशा है।यदि प्रदर्शन 21 जी से अधिक हो जाता है, तो आपको प्रोफाइल में कुछ देखना चाहिए। सबसे अधिक संभावना io प्रतीक्षा करें। – Marc

उत्तर

0

मुझे लगता है मैं इस सवाल का जवाब पाने के बारे में सोचो। क्योंकि मेरी डिस्क I/O गति लगभग 1 9 4 एम/एस है, और डिस्क बफर I/O लगभग 9 0 9 3 एम/एस है। लेकिन डिस्क बफर आकार लगभग 18166 मीटर है। इसलिए जब फ़ाइल का आकार 20 जी से छोटा होता है तो लेखन गति तेज होती है। मैंने अपनी डिस्क 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

धन्यवाद। मुझे लगता है कि मुझे जवाब मिल गया है। –