私たちは皆、生産において複雑なエラーに遭遇しましたが、これは従来の監視ツールでは見つけるのが困難です。 BPFは、事前に準備することなく、実行中の動作中のシステム上で直接高速かつ安全な動的デバッグを可能にするLinuxカーネルテクノロジーです。 JVM自体には、ガベージコレクションの追跡、オブジェクトの割り当て、JNI呼び出し、さらにメソッド呼び出しのための多くの監視ポイントがあり、追加のインスツルメンテーションは不要です。 これらの監視ポイントでは不十分な場合、Linuxカーネルとあらゆる種類のライブラリを使用して、システムコール、ネットワークパケット、スケジューライベント、ディスクアクセスに費やされた時間、さらにはデータベースクエリまで追跡できます。
このハブポストでは、BPFツールを使用してGNU / Linux上のJVMアプリケーションを監視する方法に関するSasha Goldshteinレポートのテキスト復号化と、 fileslower 、 opensnoop 、 straceなどの古典的なツールを使用したパフォーマンスチェックリストを作成しましたが、非侵襲的で高速かつ安全なBPFテクノロジーを使用します。
キャットの後、スライド付きの写真がたくさんあります。 注意トラフィック! 写真は可能な限り縮小されますが、それ以上は縮小されません。 それらはすべて本当に必要です。
今日は、最新の最先端のLinuxツールを使用した監視について説明します。 私の名前はSasha Goldsteinです。Microsoftの.NETに関連する多くのことをしています。 数年間、私はLinuxの監視およびトレースツールに関与していました。一般に、過去12年間の私の仕事はパフォーマンスに関連しています。 C ++でアプリケーションを監視するために使用されるLinux用の同じツール(私はこれを非常に頻繁に行います)、Pythonでは(時々これを行います)、LinuxでJavaアプリケーションの重要な問題を監視、改善、追跡および解決するために使用できることが判明しました。 私がしていることのいくつかは、Java開発者にとっても便利です。
講演では、専門のLinuxトレースツールと、それらをJavaアプリケーションで使用する方法について説明します。 つまり、氷山の一角だけを紹介します。これらは、他の言語や環境で使用できるシステムレベルのツールです。 したがって、Javaでしか書かれていないアプリケーションをデバッグまたはプロファイリングする必要がある場合は、Javaコードでのみ動作する多くのJavaプロファイラーとは異なり、これらのツールが便利です。
講義の中で、私はあなたに役立つと思われる4つの主要なポイントを強調します。 最初に、JVMアプリケーションで使用できる、すぐに使用できるトレースツールを正確に見つけます。 これについては少しだけ話しましょう。 第二に、これは重要なトピックの1つであり、 BPF (これはシステムレベルのテクノロジーです)、およびLinuxの最新のトレースツールで大きく変更できることについて説明します。 Linuxで実稼働中。 第三に、パフォーマンスを評価するためのツールの一種のチェックリストを示します。これを使用すると、簡単かつ迅速に予備データを取得できます。 最後に、より洗練された洗練されたツールを使用して特定の問題を解決する、焦点を絞った研究の例を示します。
展開中にLinux以外のものを使用することがある場合、他のシステムにはこれらのツールに類似したものがあります。 Windowsでは、私が話すいくつかのことでETWを実行できます。 FreeBSDおよびMacOSでは、 DTraceを使用できます。 BPFは、Linux向けのDTraceであると言う人もいるかもしれませんが、 BPFはそれを呼び出すことを好みません。
次に、Linux用のトレースツールの一般的な概要をグラフ形式で紹介します。
      
        
        
        
      
    
水平軸は詳細レベル、つまりツールが提供できる詳細情報のレベルです。 縦軸は使いやすさです。 別の色は、時間を無駄にしない新しいツール、安定したツール、および廃止されたツールを表します。
多くの場合、特にシステムレベルで作業していない開発者にとって、人々はftraceに不慣れです。 ftraceのことを聞いたことがありますか? かなり少数。 Ftraceは組み込みのメカニズムであり、昔からLinuxに組み込まれており、パフォーマンスの問題、生産中のバグをトレースするためのツールです。 ただし、Javaを使用することは意図されていません。 ガベージコレクション、クラスの読み込み、オブジェクトの割り当てなど、多くの興味深いJavaイベントをトレースするために使用することはできません。
perfに移りましょう。 あなたが使用した便利なツールはどれですか? すでにはるかに多くの人々。 私に続くスピーカーは、 perfをJavaアプリケーションで動作するように適応させる方法について話します。 私のレポートでは、 perfを使用せず、後でその理由を説明します。 しかし、私はそれがはるかに広い範囲のアプリケーションに適用可能であると言うでしょう。
次に、 SystemTap 。 どれくらいの人がそれを使ったか、聞いたことがありますか? 繰り返しますが、以前に手を挙げた人はほとんどいないようです。 SystemTapは非常に低レベルのツールであり、ユーザー空間のカーネルイベントと高レベルイベント(Javaイベントを含む)をトレースできます。 多くの人がSystemTapで遭遇する主な問題は、このツールを使用するには、実行中にカーネルモジュールをコンパイルし、カーネルにロードする必要があることです。 他の人は、動的にコンパイルされたカーネルモジュールをロードしてもそれほど熱意はありません。 SystemTapの作成者はBPFのバックエンドを開発しているため、各トレースプログラム用に新しいカーネルモジュールをコンパイルすることはできませんが、これまでのところ問題が残っています。
スペクトルの対極にあるのは、最大限の可用性と利便性ですが、機能性は劣ります。これはSysDigです。 何人使用しましたか? さらに少ない人。 SysDigは、コンテナ内のパフォーマンスの追跡に特に重点を置いた優れたツールですが、システムコールでのみ機能します。 彼はうまくやっていますが、それ以上何も知りません。 Javaアプリケーションに必要なものではありません。
今日は主にBPFベースのツールについて説明しますが、後でBPF自体に進みます。 BPFにはいくつかのフロントエンドがあり、それに基づくツールはCで作成できます。Pythonには多くのオプションがあります。 レポートで議論されるものは新しいものであり、他の人ほど安定していませんが、非常に強力です。 彼らの目新しさのために、それは時々非常に簡単ではありませんが、それは価値があります-少なくとも今日それを証明したいと思っています。
他のツールがあります。 たとえば、次のような古いもの LinuxでのDTrace 。 それはかなり野心的なプロジェクトでしたが、最終的に彼は死にました。 先ほど言ったように、この種のBPFは LinuxのDTraceであり、私たちには欠けていました。
今日、Javaが注目されているため、JVMの監視ポイントについて説明しましょう。 JVMに固有の実行中のJavaアプリケーションで追跡できるもの、つまり オペレーティングシステムによって実行されるもの(システムコール、ネットワークイベント)以外? Javaの最新バージョンでは、JVMには実行時に含めることができる多くの静的トレースポイントがあります。つまり、事前にオンにする必要はありません。 次に、必要な情報を提供するこれらのポイントにトレースプログラムを接続できます。
      
        
        
        
      
    
これらのトレースポイントのリストを取得する方法の1つを説明します。  Linuxには、 ELFヘッダーを分析してメモを作成できるreadelfツールがあります。 これらは、システム上のJavaアプリケーションに組み込まれている非常にトレースポイントを記述します。 高レベルのJavaイベントであるclass_loaded
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     、 thread_start
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     、 object_alloc
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     、これらのポイントを介してトレースできます。 
      
        
        
        
      
    
別のツールtplistがありますが、これは多少使いやすく、自分で作成しました。 単純なリストを作成するため、メモを解析する必要はありません。 ここには何十ものトレースポイントがあります。ガベージコレクション、モニターのピックアップと脱退、JNIイベント(スライドには表示されません)。
      
        
        
        
      
    
 これらのイベントにも引数があります。 時間を節約するために、この情報がどのように抽出されたかについては説明しませんが、 tplistには、これらの各観測点の引数を表示できるフラグがあります。 たとえば、常識に基づいて、 monitor__waited
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    イベントには、予想される何らかの種類のモニター情報が含まれている可能性が高いと言えます。ストリーム識別子がある可能性があります。 ただし、これらの引数が正確に何を意味するかについては、ここでは直接言及していません。 ここで、JVMに付属するテキストファイルが役立つことがわかります。ここでは、これらのトレースポイントについて説明します。 基本的に、 SystemTapトレースファイル。 たとえば、 monitor__waited
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    イベントにmonitor__waited
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    いくつかの引数monitor__waited
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    ことがわかります。これは、ストリーム識別子、モニター識別子、予想されるオブジェクトのクラス名です。 表示用のトレース用に提示できる形式オプションも提案されています。 
質問は、OpenJDK、Oracle JDK、特定のディストリビューションに関するものですか? 私の知る限り、すべてのJDKにはこれらのトレースポイントがありますが、仕様がこれを強制していることを強く疑います。 まさに彼らが生まれたとき、私は確かに言うことができません。 Oracleの記事を覚えていますが、2008年に記載されたようです。したがって、これは新しい現象ではありません。
(このレポートの後、確認しました:OracleJDKのLinuxではこれらの監視ポイントはありません 。SolarisおよびおそらくOracle Linuxにあります。これらのポイントはソースにありますが、デフォルトではコンパイルされません。しかし、すべてのOpenJDKに存在します!)
最初に、それらの使用方法を示したいと思います。次に、 BPFとそれらの使用方法について説明します。 ここに、軽薄な例があります。Javaアプリケーションは、重要と思われるメッセージをコンソールに出力しますが、どこから来たのかはわかりません。 さらに、本番環境でこれらのメッセージを送信するコードを知りたいです。 おそらくデバッガの助けを借りて、この問題はブレークポイントを介して解決できますが、それは行いません。 PreserveFramePointerフラグが必要になります 。これは、スタックを走査するために多くのJavaプロファイラーでも使用されます。 このフラグはすでにJDK 8u60に存在していましたが、 perfを使用する次のレポートで説明します。 旗は、スタックを歩くために必要です。 このフラグには、フレームレジスタ(CPUレジスタの1つ)が他のレジスタと同様に通常の計算に使用されていないことの確認が含まれます。 スタック上を歩くことを含め、一連の呼び出しを処理するためにのみ使用する必要があります。
このフラグを使用する推定コストは、約3%です。 プロセッサの負荷が非常に高くなく、1秒あたり数百万のメソッドが呼び出されない場合(おそらく0%)、これは控えめな見積もりです。 画面に、トレースしようとしているプログラムの出力が表示されます。
      
        
        
        
      
    
警告は十分に深刻に見えるため、警告の出所を理解する必要があります。 私が書いたトレースツールを使用してみましょう。 彼はシステムレベルのイベントをトレースし、途中でこれらのイベントからJava呼び出しのスタックを受け取ります。 同時に、Javaアプリケーションを再起動し、実際にトレースを再コンパイルする必要はありません。これは、実稼働環境に起動できる非常に軽量なツールです。 スライドに沿ってリンクがあり、レポートの終わりまでに、これらすべてのツールの入手先がわかります。
      
        
        
        
      
    
トレースは BPFに基づいています。 スライドには、彼への訴えがあります。 まず、注意:特権ユーザーとしてコードを実行する必要があります。 後で説明するように、 BPFでは、これとperfが他の多くのツールと同様に必要です。 次に、 トレースが正確に添付されているものを判別する必要があります。 画面への出力のトレースが必要ですが、この特定のケースではシステムレベルで作業しているので、特に標準出力を提供する特定のシステムコールを探します。 さらに、最初の引数が1つでなければならないという条件を追加します。 あなたの意見では、必要なシステムコールの最初の議論は何ですか?
 そうです、ファイル記述子、およびユニットは、出力をstdout
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    トレースするための条件です。 次に、印刷されるメッセージが表示されます。これはprintf
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    のスタイルです。 一方、 arg2
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    は、印刷のプロセスに直接あるバッファーです(テキストが含まれている場合は、ほとんどの場合)。 その後に、ユーザー空間の呼び出しスタックを示す-U
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    フラグが続きます。 最後に、Javaプロセスのみに関心があるため、Javaプロセスのみを残すフィルターを配置します。 構文を理解していただければ、これがすべて明らかになることを願っています。 
  traceの出力を見てみましょう。 彼はほとんど私たちが望んでいたものです。 最初の数行は、プロセスとフローの識別子を識別する見出しです。 次に、私たちに興味のあるメッセージが来ます-「データの受信エラー、クリア」。 コールスタックはほとんど必要なもので、最初はすべて問題ありませんが、たとえばjava_io_FileOutputStream
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    前に何が起こるかなど、最も興味深い部分は示していません。 また、Javaスタックを通過して、コード内のシンボル、関数名、およびメソッドとの通信を構築しようとする多くのツールを使用する場合、この問題が発生します。 
      
        
        
        
      
    
ここでは、 perfや他の多くのツールと同様に、JITでコンパイルされたコードのメモリ内のアドレスとメソッドの実際の名前との間の対応を出力する小さなエージェントが必要になります。 必要に応じて、ソース情報にアクセスできるため、ソース情報も印刷できます。 この場合、GitHubにあるかなり一般的で非常に単純なエージェントperf-map-agentを使用します。 出力は/ tmpフォルダーに送信されます。これらは、コードアドレス、特定のメソッドの表示、およびこのメソッドのサイズを含む非常に単純な形式のファイルになります。 これらのマッピングは、Java呼び出しスタックを解決するために必要です。 プロファイラーが最初にJavaスタックフレームの操作方法を知らない場合、そのような操作は不要です。
      
        
        
        
      
    
エージェントを使用した新しい結果であるスライドでは、スタックは受け入れられるように見えます。生成したばかりの.mapファイルから抽出された関数の名前はすべて許可されます。 スライドでは、アプリケーションのコードの一部(DataFetcher :: fetchData)が強調表示されており、コンソールへの出力が実行されて邪魔されました。 ソースが見つかりましたが、現在は状況に応じて、このコードで何をするかを決定します。 これは、必要な機能の例であるように思えます。単純で、リソースを大量に消費しない、すぐに使用できるツールを使用して、既に実行中のシステムからデータを抽出します。 これは、Javaレベル、システムレベル、カーネルレベルで発生する可能性があります-問題ではありません。
 問題の要旨に入る前に、別の同様の例を考えてみましょう。 多くのガベージコレクションを引き起こすJavaアプリケーション。 ガベージコレクターのログから、 System.gc()
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    直接呼び出すことがわかっているので、正確にどこを理解する必要があります。 アプリケーションは巨大で、多くのライブラリがあり、どのようなコードがこれらの呼び出しを行うかは不明です。 ここでは多くのリソースを必要とするフラグが必要になるため、この例から始めませんでした。 これは、 ExtendedDTraceProbes
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    と呼ばれる一種のスーパーデバッグモードであり、任意のJavaメソッドの入力および出力にトレースプログラムを添付できます。 明らかに、これには私が説明した他の方法よりも多くのリソースが必要になるため、このフラグは特定の問題を解決する必要がある場合にのみ使用してください。 
      
        
        
        
      
    
 ガベージコレクターログの前に、 System.gc()
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    直接呼び出しがあります。 ここでもトレースを使用しますが、アタッチメントの目的がわずかに異なるため、わずかに異なる方法で使用します。 
      
        
        
        
      
    
  method__entry
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    と呼ばれるJVM内のポイントになります。これを使用して、任意のJavaメソッドをトレースできます。 興味のある特定のメソッドを示すために、 arg4
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     (これはメソッドの名前です)がgc
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    と等しいことを必要とする条件に置き換えます。 おそらく、クラス名のチェックも追加する必要がありSystem
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     。これはSystem
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    でなければなりません。 次に、メッセージを出力し、その後に呼び出しスタックを出力します。 最後に、これらはすべてJavaプロセスでのみ行う必要があります。 次に、このアプリケーションの各System.gc()
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    呼び出しの呼び出しとスタックトレースがある出力があります。 これは、前回と同じコードであるDataFetcher::fetchData
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     、 RequestProcessor::processRequest
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    などの要求に応じてRequestProcessor::processRequest
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    れます。 
これは正直なフルスタックであり、JavaフレームとJVMからのネイティブフレームの両方を持ち、Linuxのルートスレッドまで、パス全体に沿って私たちを導きます。 絶対にすべてがここで見ることができます。 そのため、このようなデータを取得するために克服する必要があるものの例を次に示します。
この作業の背後にある動機付けのさらにいくつかの例...例から、すでに述べた問題に移りましょう。perfの何が問題なのでしょうか? このツールは、Linuxの実稼働環境でのJavaアプリケーションの監視またはトレースに関するすべての講演で言及されています。 前述したように、私の次の記事は、 perfを使用してJavaアプリケーションのCPUサイクルをフェッチする新しい独自の方法に関するレポートです。
      
        
        
        
      
    
  perfを使用すると、単純に動作します。最初に記録し、次に記録を処理して、たとえばフレームグラフを取得します。 おそらく、このperfの使用を認識している人もいます。 私がお話しする問題は、 BPFと私があなたに伝えたいと思う考えに関連しています。 その作業のために、 perfは後続の分析のためにファイルを介してユーザー空間に大量のデータを転送します。 特定のクラウド上に仮想マシンを作成し、このマシンに接続して、約1 Gbit / sの速度でファイルをダウンロードしました。 自宅ではそのような接続はありません。そのため、クラウド上の仮想マシンについて話していると言ったのです。 その結果、約9万のnetif_receive_skb
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    イベントが発生しました。 システムで受信したデータ、トレース遅延、パケットサイズをトレースするために、 perfでこれを記録できます。 ただし、同時に、1秒あたり9万イベントが出力されます。コールスタックを記録する場合、これはファイルに書き込まれる1秒あたり20メガバイトのデータです。 明らかに、これは通常、実稼働環境では行われません。また、ハードディスク領域が不足するだけなので、このような作業を1分以上行うことは明らかに望ましくありません。 同時に、これらの20メガバイト/秒のうち、平均パケットサイズ、パケットの受信からJavaアプリケーションへの配信までの平均遅延など、わずか5バイトに関心があるかもしれません。  1秒あたり20メガバイトは必要ありませんが、これがまさにperfの仕組みです。イベントがファイルに送信され、このファイルを分析するユーザースペースプログラムが起動します。 これがまさに私たちが解決しようとしている問題です。 私たちは、処理を直接データ収集、トレースプログラムに近づけ、自分でファイルを必要としない場合はファイルを作成しないようにしています。 
      
        
        
        
      
    
そして、ここで「Berkley Packet Filter」の略であるBPFを紹介します。 このツールは、90年代の初めから存在していました。 レポートを歴史の教訓に変えたくはありません。ここでの基盤が非常に成熟していることを示すだけです。 BPFは、パケットをフィルタリングし、システムに入るパケットをトレースし、それらを通過させるかどうかを決定するために作成されました。 tcpdump 、 Wiresharkまたは同様の追跡ツールは、どのIPアドレスから、どの特定のプロトコルでパケットを受信するかを指定するときに使用します。 どちらの場合も、 tcpdumpとWiresharkは、独自の命令セットを使用して小さなBPFプログラムを作成し、カーネルに渡します。次に、着信パケットごとにこのプログラムを実行して、このパケットを削除するかトレースするかを決定します。 私たちの目の前のスライドには、別のアセンブラーであるこの一連の指示があります。 90年代、この一連の指示は非常に簡単でした。 しかし、過去3〜4年にわたって、ネットワークの目的だけでなく、パケットのフィルタリングだけでなくBPFを使用できるようにするために、多くの努力が払われてきました。 今日、トレースはその機能の一部であり、私の主な焦点はそれです。 上記で示したトレースツールはBPFを使用します。 ただし、 BPFには他の機能があります。 さらに、Javaと同様に、 BPFにはJITコンパイラーが追加されました。 上記の一連の命令は、カーネルによって解釈されなくなり、代わりに、それらをマシンコード、プロセッサ命令にコンパイルしてから実行します。
以前、 SystemTapには問題があり、動的にコンパイルされたカーネルモジュールをロードするということを言いました。 これは、 BPFとは異なります。 後者の場合、命令のセットはarbitrary意的ではなく、セキュリティの問題を回避するために特別に選択されました。 不良なBPFプログラムは、カーネルをドロップまたはサスペンドできません。 BPFプログラムはメモリを割り当てないため、カーネルでメモリリークを引き起こすことはできません。 これらのプログラムのすべての機能は、生産に害を及ぼさないように厳しく制限されています。
主なトピックであるトレースに移る前に、いくつかのシナリオについて簡単に説明します。 ネットワーク会議で聞くことができる今日のBPFの最も重要な用途の1つは、 XDP(eXpress Data Path)です。 DDoS保護サービスを作成していると仮定します( Cloudflareは例です)。 パッケージを処理したり転送したりすることなく、できるだけ早くパッケージを削除する必要があります。 この場合、パケットがカーネル、TCPスタック、またはアプリケーションに到達する前に、 BPFプログラムが実行され、パケットを削除するか、他の誰かに転送するか、アプリケーションの最上部に送信するかが決定されます。 これは、 BPFを使用してシステムの動的ルールを設定する1つの例です。
同じ種類の別の例はseccompです。 現在のLinuxでは、 BPFプログラムをインストールして、特定のアプリケーションのシステムコールをフィルタリングできます。 アプリケーションは特定のファイルへのアクセスを拒否することができますが、他のファイルへの呼び出しは許可されます。 ハードドライブからの読み取りを許可しながら、ハードドライブへの書き込みを防ぐことができます。 システムとの対話のこのフィルターのおかげで、 BPFは一種のサンドボックスを作成します。
 主に、システム上のイベント(ガベージコレクションなど)をトレースするためのBPFの使用と、トレースのデモですでに説明したメソッド呼び出しのトレースについて説明します。 システムにはさまざまな接続ポイントがあります。アプリケーションレベルでは、これらはガベージコレクション、オブジェクト割り当て、Javaアプリケーションでのクラスロードです。 さらに、パケットの受信、システムコールのwrite
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    およびread
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    など、多くのカーネルレベルの接続ポイントがあります。 ユーザースペースには、カーネルにBPFプログラムをインストールし、それを関心のあるイベントにアタッチする制御プログラムがあります。 これらのイベントが発生すると、カーネル内のプログラムが実行されますが、次の2つのいずれかを実行できます。 情報をユーザー空間に送信でき、同時に、本質的にトレースの手段として機能します。 これが私のプログラムの仕組みであり、ユーザー空間のスクリプトを介して出力を印刷します。 または、プログラムは、集計を実行するメモリ内データ構造を更新できます。 後続の分析のためにデータをユーザースペースに転送する代わりに、カーネルで直接集計を実行し、平均、高値、安値、ヒストグラムなどを取得できます。 数百万のイベントの送信に関与することなく、トレーサーが機能する場所。 これはまさにBPFの重要な違いであり、 BPFを非常に価値のあるものにし、 perfよりも優位に立てます。 
 プログラムがカーネルで実行されると、ユーザースペーススクリプトはバッファーまたはデータ構造からデータを読み取り、必要な処理を行います。画面にメッセージを表示し、グラフ、ヒストグラムなどを作成します。  perfとは異なり、ファイルは必要でない限りどこにも作成されません。 
      
        
        
        
      
     このツールが一般に受け入れられないのはなぜですか? まず第一に、それは完全に新しいからです。  パフォーマンスをトレースおよび監視する BPFソフトウェアを使用するには、ほんの数年前の最小バージョン4.1
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     Linuxカーネルが必要です。  Ubuntu 14またはCentOS 5はサポートしていません。 最も有用なことのためには、さらに新しいカーネルが必要です。  FedoraとUbuntuの例を見てみましょう。  Ubuntu 16 LTSでは 、 Ubuntu 16.10でBPFの多くの機能を使用できます-ほとんどすべて。  BPFによって追加された最新の機能には、ほんの数か月前にリリースされた4.9
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
    カーネルバージョンが必要です。 したがって、今日は直接動作しないものもあれば、かなり新しいカーネルを搭載した特定のシステムでのみ動作するものもあります。 しかし、Linuxトレースの未来はBPFにあります。 これは、Java、Python、およびC ++-Linuxで実行されるすべての言語に適用されます。 その理由は、カーネルでトレースプログラムを実行し、後続の分析のためにすべてのデータをユーザー空間に転送する代わりに、対応表やヒストグラムの更新などの複雑なアクションを実行するためです。 
古いメソッドと新しいメソッドを比較します。 原則として、 perfを使用すると、データがファイルに送信され、このファイルが処理および分析されます。 BPF , . . , , .
. , , BPF , . BCC . , .. , , , , - Linux. . .
      
        
        
        
      
    
BCC . — , . - , . , , , , Java, MySQL, Postgres , . , , , , BPF .
      
        
        
        
      
    
, . , , , , , , . , , IO. , TCP TCP. DNS. , . , , — . , Java.
, . , . . , , BPF.
      
        
        
        
      
    
top , 100%. , , . BCC — uthreads . , Java-, . , . , . profile , ( perf ). profile Java, , PU, . , . Java, Java-, — . , perf — , java-, — .
      
        
        
        
      
    
     ,        .       ,     .       ,      .   ,   .   ,         .      ,    ,     . ,    ,     .       dd,  dnf,  Java   stress . ,      ,       Java.   Java    ,       — Prime::isPrime
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     , ,     .       ?   ,       ,     .   isPrime
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       ,       ,    ,  ,  isPrime
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
       .  ,       .          ,     ,        .  —  , , ,     CPU,       . ,     ,      BPF ,  ,          . 
      
        
        
        
      
    
      .    ,     ,       :    ,  ,      ( if(isPrime(i))
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ) .  ,       ?    ?  ,       Java-  ,      ?       BCC, argdist.         ,    .  ,     : monitor__contended__enter()
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ,   JVM. Argdist     5 ,     .  ,      — 3 , 9 .   - ,    3  9    5 ,      .   ,          ,    .   ,       .       ,     ,   JVM. 
CPU, , Java- , , , . Java-, , MySQL. , . , , . , , 50 , .
      
        
        
        
      
    
, dbstat BCC . MySQL PostgreSQL. , , . MySQL ASCII- ( , ). 3000 0 1 , 8 1 2 , . . MySQL. dbstat , , , 5 . , 2 , .
      
        
        
        
      
    
 ,       MySQL.    top ,     2%  ,      .    ,   BCC dbslower.    MySQL   ,      —    500.   dbslower ,          , call getproduct(97)
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     .       ,     ? 
      
        
        
        
      
    
     ,    trace ,      .        MySQL query__exec__start
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
          ,       .   trace  ,    call getproduct(97)``    
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     sleep(2)`. ,      ,      —    sleep(2).  ,       ,     . 
      
        
        
        
      
    
  ,         .    Java-,         .     .   Java    ,         , mysqlsniff .     .   BPF        Java   , , , socket.send()
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     .         MySQL.    ,   ,   .      ,   ,        .     ,      call getproduct(97)
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     .      ,   hibernate, beans  .,   JDBC,   .     —   , Product::load
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     , User::loadProducts
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     , Databaseey::main
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      ..    ,     ,      .        , Wireshark ,    ,      .        ,   BPF  ,   MySQL ,  ,        .       ,  ,    —   . 
      
        
        
        
      
     ,         .   MySQL         ,     Java.   Java      ,        BCC ,       . 
      
        
        
        
      
     ,    ,   . ,           ,   ,     . 
      
        
        
        
      
    
   ,         ,   .  Java-,    .         .NET, , , .     top,  ,      ,      BCC ustat .        Java,        .   800, , ,  , , ,    .        profile,  ,      .     ResponseBuilder::addLine
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ,      ,          . 
      
        
        
        
      
    
    ,  BCC        Java, Ruby     — uobjnew.      ,     ExtendedDTraceProbes .  ,       ,     ,    ,    .  5       ,        Java.          ,            .   uobjnew  ,     ,  ,  .    ,       ,         — stackcount .       object__alloc
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
      JVM,      ,       .    ,       ,     .     ,    : _new_array_Java
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ,  ResponseBuilder::AddLine
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     . ,       —  JVM,    SharedRuntime::dtrace_object_alloc
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     —     . 
      
        
        
        
      
     ,  ,      .     ,     ,  ,         . -,        ,     ,     . 
      
        
        
        
      
    
   .  ,    ,       — «  ».       ,       ,  ,    ,  ?         opensnoop,                   .  -x   .  ,          /etc
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     ,    — 2,   Linux  «  »,   . ,  ,          .    trace.       open,       «-2».       Java.         .  ,        , ,        .  ,       Java. 
, . HTTP- . , . , , , , 1.4-2 . 6 — , - . — facebook.com, — i-dont-exist-at-all.com, . . . , , 5 .
, , DNS , . . BCC DNS. DNS . , DNS , . . , ? trace , «-2», « », .
      
        
        
        
      
    
dig — , , , , BCC. DNS i-dont-exist-at-all.com dig : , , , 15 , . . . « » 0, . dig . DNS.
      
        
        
        
      
    
         .  ,     DNS-,   ,    800  - .      -   . ,            DNS   0
      
      
        
        
        
      
    
        
        
        
      
      
        
        
        
      
    
     . ,     ,    Java     DNS     .       ,     ,       BPF ,   DNS. 
      
        
        
        
      
       ,       ,     :    ,     JVM-;  BPF      Linux;   ;     . ご清聴ありがとうございました。 
      
        
        
        
      
    
      広告の分。 おそらくご存知のように、会議を行っています。 次はJBreak 2018とJPoint 2018です。 そこに来て、さまざまなファッショナブルな技術の開発者とライブでチャットできます。たとえば、Azul Systemsの副CTOであるSimon Ritterがいます。 c " " . ( olegchir ) . 要するに、私たちはあなたを待っています。