golangにおける効率的なコーディングの詳細
xdm、我々はgolangが本質的に高度に並列化され、効率的なコンパイル言語であることを知っています。
しかし、優れたツールも正しく使わなければ意味がないことも知っています。そこで、よくある2つの経路をたどって、その感触を確かめてみましょう
構造体と地図はどちらを使いますか?
計算量が少ないうちは、一時構造体とマップの使い分けがわからないかもしれませんが、計算量が多くなるにつれて、その差は歴然とし、計算量が多くなるにつれて、その差は歴然とします
キーも値も固定できるような状況では、マップよりも構造体を選んだ方がはるかに効率的です
- ループを1億回シミュレートして、それぞれのデータ構造を使ってどれだけの時間がかかるか見てみましょう。
- ループ前の現在時刻を計算する ループ後の現在時刻を計算する 最後に、2つの時間の差を計算します。ここではミリ秒を使用します。
func main() {
t1 := time.Now().UnixNano()/1e6
for i := 0; i < 100000000; i++ {
var test struct {
name string
hobby string
hobby string }
test.Name = "xiaomotong"
test.hobby = "program"
t2 := time.}
t2 := time.Now().UnixNano()/1e6
fmt.Println("t2 - t1 == ", t2-t1)
}
プログラムを実行して効果を確認します。
<ブロッククオート
# go run main.go
t1 == 1634377149185
t2 == 1634377149221
t2 - t1 == 36
structのアプローチで36msかかるというのは、どんな感じなのでしょうか?
マップのアプローチを見てみましょう。
func main() {
t1 := time.Now().UnixNano()/1e6
fmt.Println("t1 == ", t1)
for i := 0; i < 100000000; i++ {
var test = map[string]interface{}{}
test["name"] = "xiaomotong"
test["hobby"] = "program"
}
t2 := time.Now().UnixNano()/1e6
fmt.Println("t2 == ", t2)
fmt.Println("t2 - t1 == ", t2-t1)
}
プログラムを実行して効果を確認します。
<ブロッククオート
# go run main.go
t1 == 1634377365927
t2 == 1634377373525
t2 - t1 == 7598
構造体のアプローチを使用すると、7598msかかります。
同じデータに対してmapとstructを使った場合の時間差は212倍ですが、上記のシナリオでコーディングする場合、あなたならどちらのデータ構造を選びますか?
なぜこれほどまでに差が出るかというと
フィールドを決定できるところでは、実行時に動的にコンテンツを割り当てる必要のない一時的なStructsを使用しています。
これはmapの場合とは異なり、インデックスをチェックする必要があるため、非常に時間のかかる作業となります
文字列はどのように継ぎ足されるのですか?
仕事でxdmをコーディングする際、文字列のスプライシングをどのように実装していますか?私たちのツールでは、今のところ次のようなものが提供されています。
- を使った方法
- fmtを使ったSprintf()。
- strings.Joinを使用する
- bufferメソッドを使用する
これを見て、自分なりの答えが出るかもしれませんが、同じ文字列のスティッチングのケースで、それぞれどのような処理に時間がかかるのか、実際に見てみましょう
のアプローチでは
文字列を50万回追加するループを計算し、その時間を見てみましょう。
func main() {
t1 := time.Now().UnixNano() / 1e6
fmt.Println("t1 == ", t1)
s := "xiao"
for i := 0; i < 500000; i++ {
s += "motong"
}
t2 := time.Now().UnixNano() / 1e6
fmt.Println("t2 == ", t2)
fmt.Println("t2 - t1 == ", t2-t1)
}
の効果を見るためのプログラムが実行されます。
# go run main.go
t1 == 1634378595642
t2 == 1634378743119
t2 - t1 == 147477
このデータxdmを見ると、あまりの遅さにショックを受けます。147477ms、つまり2分27秒もかかっているのです!?
Goの+付き文字列の処理は、データからわかるように、非常にパフォーマンスが高いです
Sprintf()をfmtとする。
func main() {
t1 := time.Now().UnixNano() / 1e6
fmt.Println("t1 == ", t1)
s := "xiao"
for i := 0; i < 500000; i++ {
s = fmt.Sprintf("%s%s",s,"motong")
}
t2 := time.Now().UnixNano() / 1e6
fmt.Println("t2 == ", t2)
fmt.Println("t2 - t1 == ", t2-t1)
}
プログラムを実行して効果を確認します。
<ブロッククオート
# go run main.go
t1 == 1634378977361
t2 == 1634379240292
t2 - t1 == 262931
このデータを見て、262931ms、合計4分22秒かかっていることにも唖然。xdmは、fmt.Sprintfを使ったほうが、+を使ったときより遅くなるとは思っていなかったのでしょう。
文字列.Joinを使用する
func main() {
t1 := time.Now().UnixNano() / 1e6
fmt.Println("t1 == ", t1)
s := "xiao"
for i := 0; i < 500000; i++ {
s = strings.Join([]string{s,"motong"},"")
}
t2 := time.Now().UnixNano() / 1e6
fmt.Println("t2 == ", t2)
fmt.Println("t2 - t1 == ", t2-t1)
}
プログラムが実行され、効果を確認することができます。
<ブロッククオート
# go run main.go
t1 == 1634379455304
t2 == 1634379598227
t2 - t1 == 142923
142923ms、つまり2分22秒かかっており、これは+方式を使った場合と同等である
バッファー方式を使用した場合
バッファの使い方は、本来は
func main() {
t1 := time.Now().UnixNano() / 1e6
fmt.Println("t1 == ", t1)
s := bytes.NewBufferString("xiao")
for i := 0; i < 500000; i++ {
s.WriteString("motong")
}
t2 := time.Now().UnixNano() / 1e6
fmt.Println("t2 == ", t2)
fmt.Println("t2 - t1 == ", t2-t1)
}
# go run main.go
t1 == 1634378506021
t2 == 1634378506030
t2 - t1 == 9
上記のデータから、同じものを50万回スプライシングすると
- 1回目は、+方式で、147,477msかかります。
- 2番目はfmt.Sprintf()を使用した場合で、262931msです。
- 3番目はstrings.Joinを使用した場合で、142923ミリ秒かかります。
- 4番目は、バッファを使用した場合で、9msです。
バッファリング方式は、1番目と比較して16,386倍、2番目と比較して29,214倍、3番目と比較して15,880倍速い
xdmさん、あなたが上記のシナリオになったら、どの方法を選びますか?
golangの効率的なコーディングの詳細についてのこの記事は以上です。golangでの効率的なコーディングの詳細については、Scripting Houseの過去の記事を検索するか、以下の記事を引き続き閲覧してください。
関連
-
Go言語基本スライスの作成と初期化例詳細
-
golang 開発 インストール go-torch フレームチャート 操作手順
-
golang ソートによるプログラミング開発 詳細
-
Go言語7つの入門チュートリアル7つのGCガベージコレクション3つのカラーマーカ
-
Go言語 初心者のための7つのチュートリアル VI ネットワーク・プログラミング
-
Go言語並行プログラミングのための相互排除ロックMutexと読み取り/書き込みロックRWMutex
-
Go(...)の3つのポイントを徹底分析 使用方法
-
Go サービスでリンクトレースを行う方法を説明します。
-
小学生でもわかるGolangの例外処理リカバリーパニック
-
Goにおける文字列と[]byteの効率的な相互変換の例
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン