2016-10-31 6 views
2

私は単純なネット/ httpウェブサーバーを持っています。それがするのは、100MBのランダムバイトを配信することです。ネットワーク速度テストに使用する予定です。 100MBのエンドポイントのハンドラは本当にシンプルです(下にペーストされています)。コードは正常に動作し、私はランダムなバイトファイルを取得します。問題は実行して誰かが100メガバイトをダウンロードし、このプログラムのCPUが最大150%を撮影し、このハンドラの実行が終了するまでそこにとどまります。私はここで何か非常に間違っているのですか?このハンドラのパフォーマンスを改善するために私は何ができますか?シンプルなWebサーバーでGolangのCPU使用率が高い理由を理解できませんか?

func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error) 

そして、あなたはそれを大きな、8キロバイトのフォーマット文字列を渡します。

func downloadHandler(w http.ResponseWriter, r *http.Request) { 
    str := RandStringBytes(8192); //generates 8192 bytes of randomness 
    sz := 1000*1000*100; //100Megabytes 
    iter := sz/len(str)+1; 
    w.Header().Set("Content-Type", "application/octet-stream") 
    w.Header().Set("Content-Length", strconv.Itoa(sz)) 
    for i := 0; i < iter ; i++ { 
     fmt.Fprintf(w, str) 
    } 
} 

答えて

6

問題はfmt.Fprintf()フォーマット文字列を期待していることです。 fmtパッケージは、書式文字列を分析する必要がありますが、出力にそのまま出てくるものではありません。最も確かにこれはあなたのCPUを食べているものです。

ランダムな文字列は、fmt.Fprintf()は、あなたが「提供」していない、さらに議論を期待するかもしれないとさえ、あなたのケースは、悪化させるという特殊な%記号を、含まれているため、fmtパッケージには、エラーメッセージが含まれる(だろう)しなければならない場合

fmt.Fprintf(os.Stdout, "aaa%bbb%d") 

出力:代わりに

aaa%!b(MISSING)bb%!d(MISSING) 

使用fmt.Fprint()フォーマット文字列を期待していません:

0のような出力、中
fmt.Fprint(w, str) 

あるいはさらに良い、一度バイトのスライスに、あなたのランダムな文字列を変換し、ちょうどそれを書いておいてください。

data := []byte(str) 
for i := 0; i < iter; i++ { 
    if _, err := w.Write(data); err != nil { 
     // Handle error, e.g. return 
    } 
} 

大量のデータを届ける - あなたが書くよりも速く解決策を得ることはありませんループ内に準備されたバイトスライス(スライスのサイズを変えた場合は多分)。あなたの解決策が依然として「遅い」場合は、わからないRandStringBytes()関数が原因である可能性があります。他のハンドラやフレームワーク(比較的高いCPUを使用する)を使用すると、出力が圧縮される(gzipped) )。また、応答を受け取ったクライアントがあなたのコンピュータ(ブラウザなど)にもある場合、ファイアウォール/ウイルス対策ソフトウェアは、悪意のあるコード(リソースを大量に消費する可能性があります)の応答をチェック/分析します。

+0

あなたの提案を試してみましたので、文字列をバイトスライスに変換しましたが、これはパフォーマンスを向上させますが、CPU使用量を減らすようには見えません。 – freezingfire

+0

@freezingfire追加のパフォーマンス問題に対処するための編集済みの解説を参照してください。 – icza

+0

RandStringBytes()はランダムなデータでbytesliceを埋め尽くすだけで、このプログラムやファイアウォールやアンチウイルスには他のハンドラはありません。結局、100Mbのランダムファイルを作成し、http.ServeContentを使ってそれを配信しました。現在、取得する最大CPUは60%で、これは150%からの大幅な改善です。 – freezingfire

関連する問題