Go開発者ツール:プロファイラーラベルを理解する

描画 こんにちは 私の名前はマルコです。 私はBadooのシステムプログラマです。 Go 1.9の新機能に関するrakyllのすばらしい投稿の翻訳を紹介します。 ラベルはGoプログラムのプロファイリングに非常に役立つと思われます。 たとえば、Badooでは、Cプログラムのコードにタグを付けるために同様のものを使用します。タイマーがトリガーされ、スタックトレースがログに表示される場合、それに加えて、そのようなタグを表示します。 たとえば、特定のUIDを持つユーザーの写真を処理したと言えます。 これは非常に便利であり、Goでも同様の機会が得られたことを非常に嬉しく思います。







プロファイラーラベルはGo 1.9で登場しました。CPUプロファイラーが作成するサンプルにキーと値のペアを追加する機能です。 プロファイラーは、プロセッサーが最も時間を費やす最もホットな機能に関する情報を収集して表示します。 従来のCPUプロファイラーの出力は、関数の名前、ソースファイルの名前、このファイルの行番号などで構成されます。 このデータから、コードのどの部分がこれらのホット関数を呼び出したかを理解することもできます。 出力をフィルタリングして、特定の実行ブランチのより深い概念を取得することもできます。







完全な呼び出しスタックに関する情報は非常に役立ちますが、これはパフォーマンスの問題を見つけるのに必ずしも十分ではありません。 多数のGoプログラマーがGoを使用してサーバーを記述しますが、サーバーのパフォーマンスの問題がどこにあるかを理解することはさらに困難です。 ある実行ブランチを別の実行ブランチから分離することは困難です。または、1つの実行ブランチのみが問題を引き起こす場合(一部のユーザーまたは特定のハンドラー)を理解することは困難です。 Go 1.9からは、現時点で何が起こっているかのコンテキストに関する追加情報を追加し、この情報をプロファイラーで使用して、より孤立したデータを取得する機会があります。







ラベルは多くの場合に役立ちます。 最も明らかなものを次に示します。









ラベルを追加する



runtime/pprof



runtime/pprof



ラベルを追加するためのいくつかの新機能がruntime/pprof



ます。 ほとんどのユーザーは、コンテキストを取得してラベルを追加し、新しいコンテキストをf



関数に渡すDo



関数を使用します。







 func Do(ctx context.Context, labels LabelSet, f func(context.Context))
      
      





現在のゴルーチン内でのみラベルセットを記録します。 fで新しいゴルーチンを作成する場合、引数としてコンテキストを渡すことができます。







 labels := pprof.Labels("worker", "purge") pprof.Do(ctx, labels, func(ctx context.Context) { //  - ... go update(ctx) //    })
      
      





上記の作業には、 worker:purge



ラベルが付けられます。







プロファイラーの出力を確認します



このセクションでは、ラベル付きプロファイラーの使用方法を示します。 興味のあるコードをすべてラベルでマークしたら、コードをプロファイリングしてプロファイラーの出力を確認します。







この例では、 net/http/pprof



を使用しnet/http/pprof



。 詳細については、 Goプログラムプロファイリングの記事を参照してください。







 package main import _ "net/http/pprof" func main() { //  ... log.Fatal(http.ListenAndServe("localhost:5555", nil)) }
      
      





CPUの使用に関するデータを収集します...







 $ go tool pprof http://localhost:5555/debug/pprof/profile
      
      





ユーティリティがインタラクティブモードになった後、 tags



コマンドを使用して、記録されたすべてのラベルを表示できます。 Go標準ライブラリではラベルと呼ばれていますが、pprofユーティリティはタグに名前を付けることに注意してください。







 (pprof) tags http-path: Total 80 70 (87.50%): /messages 10 (12.50%): /user worker: Total 158 158 ( 100%): purge
      
      





ご覧のとおり、2つのキー( http-path



worker



)とそれぞれにいくつかの値があります。 http-pathキーはHTTPハンドラーを指し、worker:purgeは上記の例のコードを指します。







ラベルでフィルタリングすると、たとえば/user



ハンドラーからのコードのみに焦点を合わせることができます。







 (pprof) tagfocus="http-path:/user" (pprof) top10 -cum Showing nodes accounting for 0.10s, 3.05% of 3.28s total flat flat% sum% cum cum% 0 0% 0% 0.10s 3.05% main.generateID.func1 /Users/jbd/src/hello/main.go 0.01s 0.3% 0.3% 0.08s 2.44% runtime.concatstring2 /Users/jbd/go/src/runtime/string.go 0.06s 1.83% 2.13% 0.07s 2.13% runtime.concatstrings /Users/jbd/go/src/runtime/string.go 0.01s 0.3% 2.44% 0.02s 0.61% runtime.mallocgc /Users/jbd/go/src/runtime/malloc.go 0 0% 2.44% 0.02s 0.61% runtime.slicebytetostring /Users/jbd/go/src/runtime/string.go 0 0% 2.44% 0.02s 0.61% strconv.FormatInt /Users/jbd/go/src/strconv/itoa.go 0 0% 2.44% 0.02s 0.61% strconv.Itoa /Users/jbd/go/src/strconv/itoa.go 0 0% 2.44% 0.02s 0.61% strconv.formatBits /Users/jbd/go/src/strconv/itoa.go 0.01s 0.3% 2.74% 0.01s 0.3% runtime.memmove /Users/jbd/go/src/runtime/memmove_amd64.s 0.01s 0.3% 3.05% 0.01s 0.3% runtime.nextFreeFast /Users/jbd/go/src/runtime/malloc.go
      
      





この出力には、 http-path:/user



ラベルでマークされたサンプルのみが含まれhttp-path:/user



。 そしてこの結論では、最もロードされた場所/ユーザーハンドラがどこにあるかを簡単に理解できます。







追加のフィルタリングのためにtagshow



taghide



およびtagignore



を試すこともできます。 たとえば、 tagignore



を使用すると、特定のラベルを除くすべてのラベルのデータを取得できます。 以下のフィルターは、/ユーザーハンドラー以外のすべてを返します。 この場合、これはworker:purge



およびhttp-path:/messages



です。







 (pprof) tagfocus= (pprof) tagignore="http-path:/user" (pprof) tags http-path: Total 70 70 ( 100%): /messages worker: Total 158 158 ( 100%): purge
      
      





フィルタリングされたデータを視覚化しようとすると、出力には各ラベルが完全な「コスト」にどれだけの影響を与えるかが示されます。













worker:purge



が0.07を導入し、 messages 0.03s



ハンドラがgenerateID



関数にmessages 0.03s



を導入したことがわかります。







自分で試してみてください!



ラベルを使用すると、単純な呼び出しスタックからは利用できない追加情報をプロファイラーに追加できます。 プロファイラーで追加のディメンションが必要な場合は、 Go 1.9 betaのベータ版をダウンロードして、今すぐ試用できます。 また、 pprofutil



パッケージを使用して、HTTPパスをラベルで自動的にラップします。







Go 1.9 beta 2は現在利用可能です。 既知のバグはありませんが、開発チームはプログラムで試してみて、問題が発生した場合はバグトラッカーに報告してください。 Goをアセンブルし、開発の最先端にいることは非常に簡単です。 アセンブリ自体は1分もかかりません。 がんばれ!








All Articles