2010-12-29 7 views
3

私は、トレース/ロギングフックを非常に性能に敏感なドライバコードに挿入するための最小オーバーヘッドの方法を探しています。このロギングは常にコンパイルされなければなりませんが、ほとんどの場合、何もしません(しかし、非常に速いことは何もしません)。トレースフックの自己修正コードですか?

if(enabled){log()}を実行するだけで、グローバルオン/オフワードを持つよりもずっと簡単なことはありません。しかし、可能であれば、私は自分のフックのいずれかを押すたびにその単語を読み込むコストを避けたいと思っています。それは私が潜在的に自己修正コードを使用する可能性が私に発生する - 私は私のトレース機能への呼び出しを持っているすべての場所で、私はNOPでジャンプを上書きし、フックを無効にしたい時にジャンプを置き換えるそれらを可能にする。

急いでgoogleはこれに関する先行技術を立てていません。それは実現可能ですか?私が予見していない主要な障害物はありますか?

(Linuxでは、x86_64版)

+1

書き込み/実行モードの排他性の可能性に注意してください。それは、より難しくなる自己修正コードを書けるようにすることができます... – dmckee

答えて

4

はい、この手法は、まったく同じ目的(トレースフック)のために、Linuxカーネル内で実装されています。

開始点はthe LWN article on Jump Labelsを参照してください。

大きな障害はありませんが、多少のマイナーなものがあります。マルチスレッドプロセス(コードを有効または無効にしている間に他のすべてのスレッドを停止する必要があります)。インコヒーレントな命令キャッシュ(Iキャッシュがフラッシュされることを保証する必要があります.、すべてコア)。

+0

ありがとう、これは私が探していたものです。 – kdt

0

何とかグローバルレジスタを宣言するための方法があった場合は、外からあなたのドライバーにすべてのエントリポイントであなたのワードの値をレジスタにロードし、ちょうどチェックすることができます登録簿。もちろん、オプティマイザへのそのレジスタの使用を拒否することになります。これはパフォーマンスに悪影響を及ぼす可能性があります。

+0

'register'キーワードでグローバル変数を宣言することはできません。可能であれば、そのレジスタをすべて失うという恐ろしい、ひどい考えです。 –

+0

@Adam Rosenfield - 実際にはいくつかのCコンパイラでレジスタグローバルを宣言する方法があります。特に埋め込まれたもの。そして、他のすべてのためにそれを失うことは非常に悪いでしょう。私はちょうど有効なアイデアを投げ捨て、その欠点を指摘しました。私はそれが下降投票に値するとは思わないが、何でも。私はここに私の答えを残している。 – Omnifarious

+0

これは組み込みアーキテクチャでは合理的なアプローチですが、残念ながら少なくともx86_64で動作する必要があり、理想的には移植可能です。私はあなたがなぜ落選したのか分かりません... – kdt

4

あなたのコンパイルされたドライバが突然2倍の大きさであれば重要ですか?

2つのコードパスを構築します.1つはロギング、もう1つはロギングを行います。グローバル関数ポインタを使用して、パフォーマンス重視のセクションにジャンプし、必要に応じて上書きします。

0

これは可能かどうかの問題ではなく、何か重要なものが得られた場合は、あまり書いていません。

ロギングの可能性が現れるたびに、「ロギングが有効」であることをテストする必要はなく、「ロギングが有効」であることをテストし、コードを「はい」または「いいえ」で上書きする必要があるコード。または、あなたのドライバーは、それが最後の時間ではなかったことを覚えていますか?今度は何も要求されていないので、何もする必要はありませんか?

必要なロジックは、毎回テストと比較して些細なものではないようです。

+0

あなたは誤解しています。書き直しフックを使用しているときは、トレースがオンになっている(トレースコードを挿入している)か、オフになっている(何もしていないコードに置き換えられる)作業が行われるのは唯一の時間です。全体のポイントは、トレースをオフにすると、トレースポイントはノーオプスになります。 – kdt

+0

私が意味することは、トレースコードを挿入するか、何もしないコードに置き換えるのに必要なロジックとコードが、no-opsを実行することによって得られた時間を無駄にするかもしれないということでした。 –

関連する問題