GO言語のパフォーマンス問題の発見と解決

GO言語のパフォーマンス問題の発見と解決

事件の原因

この事件は、社内の同僚が社内メーリンググループに質問を投稿したことから始まりました。 go1.8.3 で書かれたビジネス プログラムをしばらく実行した後、一部の goroutine がロック ForkLock を待機して停止しました。同僚は、これは go1.8.3 のバグだと考えており、go1.10 にアップグレードした後も再発しませんでした。これを理解するために、同僚が github https://github.com/golang/go/issues/26836 に問題を投稿し、再現を何度も試みましたが、うまくいきませんでした。

問題が発生したビジネスコードを参照しました。大まかな使用方法は、親プロセスが os/exec の下のコマンドを呼び出して子プロセスを開き、シェル コマンドを実行することです。次に、コマンドは golang によってカプセル化された forkExec を呼び出して子プロセスを開き、コマンドを実行します。 forkExec は ForkLock を使用します。

問題分析

ForkLock は、次のような状況を回避するために存在します。複数の goroutine が同時に exec を fork する場合、子プロセスが必要なファイル記述子のみを継承するには、親プロセスがこれらのファイル記述子を作成するときに O_CLOEXEC フラグを追加して、これらの記述子が子プロセスで閉じられ、子プロセスが必要に応じて継承する必要がある記述子を開くことができるようにする必要があります。

Linux 2.6.27 以降では、ファイルやパイプを開いたり、O_CLOEXEC を設定したりすることはアトミック操作なので、大きな問題はありません。ただし、golang ではカーネル バージョンが 2.6.23 以上である必要があります。さらに、Unix システムでは、オープンと O_CLOEXEC の設定は 2 つの操作です。 2 つの操作間でフォークが発生した場合、子プロセスは必要のないファイル記述子を継承する可能性があるため、ロックが必要になります。 forkExec のソースコードに注目してください。

問題の現象から判断すると、goroutine が forkExecPipe または forkAndExecInChild ステップでスタックし、ロックが解除されない状態になっていると考えられます。そのため、一部のゴルーチンはロックを取得できず、飢餓状態になります。 forkExecPipe*** はカーネル pipe2 を呼び出し、forkAndExecInChild*** はカーネルの clone と exec を呼び出します。

推測

pipe2 は高速なシステム コールなので、ブロックされる可能性があるシステム コールは clone と exec です。なお、この問題はgo1.10では再発しません。 forkAndExecInChild 関数における go1.8 コードと go1.9 の違いを比較します。

1.8 に行く

1.9 へ

go1.9 では CLONE_VFORK と CLONE_VM が追加されました。 SIGCHILD のみを使用したクローン作成は、fork に似ていると考えられます (*** 両方とも do_fork を呼び出します)。 fork の問題は、親プロセスがより多くのメモリを占有するため、パフォーマンスが低下することです。詳細については、次のリンクを参照してください: https://bugzilla.redhat.com/show_bug.cgi?id=682922

このケースは 2011 年に提案され、今年 7 月時点でも更新中でした。この場合に反映される問題は、Linux カーネルがコピーオンライト メカニズムを導入したにもかかわらず、フォーク中にページ テーブルをコピーする必要があることです。プロセスの仮想メモリが大きいほど、コピーする必要があるページ テーブル エントリの数が多くなり、フォークが遅くなります。 Golang ディスカッション グループの誰かがテストしたところ、ヒープ サイズが 2G の場合、フォークにかかる時間はミリ秒単位まで短縮される可能性がある一方、通常は数十マイクロ秒であり、その差は数千倍にもなるとのことです。

Go1.9 では、子プロセスと親プロセスがメモリを共有できるようにするために、これら 2 つのパラメータが追加されました。これは、vfork を呼び出すのと同等です。ページテーブルをコピーする必要がないため、作成速度が速くなります。テスト結果から、数十マイクロ秒で安定しています。

したがって、go1.9 より前のバージョンで書かれたプログラムでは、プログラムのメモリ使用量が十分に大きく、プロセス作成の頻度が十分に高い場合、ForkLock は長時間待機することになるというのが妥当な推測です。

実験的デモンストレーション

go1.8.3 を使用してテスト プログラムを作成し、2 コア 4G 仮想マシン (カーネル 3.10.0-693.17.1.el7.x86_64) でテストしました。

10 秒ごとに、プログラムに SIGUSR1 信号が送信され、ランタイム スタックが印刷されます。しばらく実行すると、一部の goroutine では ForkLock を取得するのにかかる時間がどんどん長くなります。以下の2枚の写真をご覧ください。

ただし、go1.9以上では上記のような状況は発生しませんでした。この結果は問題を説明するのに十分だと思います。バージョンを go1.9 以上にアップグレードすると、この問題を解決できます。

***で書かれた

vfork は、ページ テーブル エントリをコピーするフォークによって発生するパフォーマンスの問題を解決するように設計されています。ほとんどのシナリオでは、exec は fork の後に呼び出されます。 Exec はすべてのページ テーブルを削除し、新しいページ テーブルをリセットします。ページ テーブル エントリを再度コピーする必要はまったくありません。ただし、vfork の親プロセスと子プロセスはメモリを共有するため、使用時には十分に注意する必要があります。子プロセスが変数を変更すると、親プロセスに影響し、カーネルは親プロセスを一時停止して、子プロセスを先に実行させます。これらの制限により、vfork は基本的に exec を使用するシナリオに制限され、fork ほど汎用的ではありません。

vfork は注意して使用する必要があり、go1.9 が vfork とともにリリースされる前に、rawVforkSyscall が戻った後も命令は親プロセス セグメントで実行されるため、子プロセスが両者の共有スタックを破壊する可能性があるため、コードが十分に堅牢ではないという意見がありました。そのため、図に示すように、この相互影響を解決するために、rawVforkSyscall が親プロセス セグメントで何もせず、戻った後に直接戻ることを許可するコミットが提案されました。

さらに詳しく知りたい場合は、Rob Pike 氏や他のユーザーがコメントしているこのコミットのレビューを参照してください。

https://go-review.googlesource.com/c/go/+/46173

<<:  クラウドコンピューティングの相互接続の未来とは?

>>:  アリババクラウドとHuyaが共同でライブストリーミング業界向けのエッジノードとクラウドエンタープライズネットワークサービスを初めて開始

推薦する

SAPが第1四半期の財務報告を発表:クラウドコンピューティングの収益は22億ユーロ、前年比7%増

ドイツのビジネスソフトウェア大手SAPは4月13日、第1四半期の財務報告書を発表し、新たなエンタープ...

分散システムの一貫性保証ソリューションの概要

導入インターネットシステムでは、理想的には、システムが「一貫性」、「可用性」、および「パーティション...

Windows で securecrt を使用して VPS サーバーに接続するチュートリアル

SecureCRT は、Windows で Linux サーバーに接続するためのソフトウェアです。こ...

spinservers: 米国独立サーバー、月額 69 ドル、e3-1280v5、32gDDR4、1TNVMe、30T トラフィック/2*10Gbps 帯域幅

spinservers は、米国サーバーのプロモーションを新たに開始しました。今回は、e3 のハイエ...

Baidu のプロモーションは費用がかかりすぎます。ヘルスケア製品業界はプロモーション費用をどのように削減できるでしょうか?

私は一時期、女性向けヘルスケア製品会社で働いていました。主にウェブサイトの運営と百度のプロモーション...

外部リンクに関する個人的な見解についての簡単な議論

私は長年 SEO に携わってきましたが、多くのウェブマスターが私と同じように、外部リンクへの道がます...

B2B ブログ SEO 運用のヒント

ブログは、企業に顧客とのよりカジュアルでパーソナライズされたコミュニケーション方法を提供します。SE...

Visual Chinaの広報危機について話しましょう!

コアヒント:画像の著作権は中国の画像ビジネスモデルの基盤であり、世界を征服するための武器です。しかし...

百度百科事典の作り方は?百度百科事典のプロモーション効果分析

Baidu 百科事典は、Baidu が立ち上げたオンライン百科事典で、オープンなコンテンツ、厳格なレ...

効果を最大化するためにソフト記事のプロモーションチャネルを選択するにはどうすればよいでしょうか?

はじめに:ソフト記事のプロモーション チャネルを選択することは決して難しいことではありません。難しい...

百度は淘宝網から遠く離れているが、360度検索はかなり信頼できる

昨日、Taobao の広告を掲載しているウェブサイトは Baidu によって簡単に降格される可能性が...

Baidu をフォローしてクロールし、Baidu にサイトを更新させましょう。

スパイダー SEO: Baidu をクロールさせ、Baidu に Web サイトを更新させましょう。...

Photonvps-KVM 簡易評価 (512M メモリ)

photonvps で新しい KVM VPS がリリースされた後、Hostcat はすぐに 512M...

黒人チェーン店がイメージチェンジで復活

フレンドリー リンクは今でも役に立ちますか? 間違いなく、効果的です。Baidu は、「推奨の重要性...