すべてのリクエストのレスポンス ストリームをインターセプトし、テキスト/HTML タイプのレスポンスごとに 6 ~ 12 個の Regex.Replace() を実行する HttpModule を実装しました。ここでどれだけのパフォーマンス ヒットが発生するかが心配です。調べる良い方法は何ですか? この HttpModule を実行している場合と実行していない場合の速度を比較したいと思います。
4 に答える
Response.Filter ストリーム パイプラインにフックして、リソース ファイルの統合、JS/CSS のパッキング、および静的ファイルの絶対パスへの書き換えを提供するものをいくつか用意しました。
RegexBuddy で正規表現の速度を数百万回の反復でテストする限り、必ず RegexOptions.Compiled を使用してください。多くの場合、最も迅速で効率的な手法は、正規表現を使用して一致を広く識別し、C# を使用してそれを磨くことです。まさにあなたが必要とするものに。
依存するキャッシュと構成も行っていることを確認してください。
私たちはこれで多くの成功を収めました。
Httpモジュールは単なる一般的なコードであるため、この特定の正規表現置換の実行時間を測定できます。十分です。ストレステストの入力として一連の典型的な応答ストリームを用意し、Stopwatch
クラスを使用して置換の実行を測定します。RegexOptions.Compiled
切り替えも検討してください。
ここにいくつかのアイデアがあります:
- Add some Windows performance counters, and use them to measure and report average timing data. You might also increment a counter only if the time measurement exceeds a certain threshold. and
- Use tracing combined with Failed Request Tracing to collect and report timing data. You can also trigger FRT reports only if page execution time exceeds a threshold.
- Write a unit test that uses the Windows OS clock to measure how long your code takes to execute.
- Add a flag to your code that you can turn on or off with a test page to enable or disable your regex code, to allow easy A/B testing.
- Use a load test tool like WCAT to see how many page requests per second you can process with and without the code enabled.
私は最近、私が書いた HTTPModule でいくつかの pef テストを行う必要があり、いくつかの負荷テストを実行して Web トラフィックをシミュレートし、モジュールが構成されている場合とされていない場合のパフォーマンス時間をキャプチャすることにしました。モジュールをインストールすることの影響を実際に知ることができる唯一の方法でした。
通常は Apache Bench で何かを行います (intsall の方法については、以下のWindows 7 に Apache Bench をインストールする方法を参照してください) が、Windows 認証も使用する必要がありました。ab
基本認証しかないので、私には合いませんでした。ab
滑らかで、さまざまな要求シナリオが可能であるため、最初に確認する場所になります。もう 1 つの考えは、 glimpseを使用することでも多くの可視性を得ることができるということです。
私は使用できなかったのでab
、同時リクエストを許可し、異なる URL 時間をテストするカスタムを作成しました。
以下は、モジュールをテストするために私が思いついたものです。
// https://www.nuget.org/packages/RestSharp
using RestSharp;
using RestSharp.Authenticators;
using RestSharp.Authenticators.OAuth;
using RestSharp.Contrib;
using RestSharp.Deserializers;
using RestSharp.Extensions;
using RestSharp.Serializers;
using RestSharp.Validation;
string baseUrl = "http://localhost/";
void Main()
{
for(var i = 0; i < 10; i++)
{
RunTests();
}
}
private void RunTests()
{
var sites = new string[] {
"/resource/location",
};
RunFor(sites);
}
private void RunFor(string[] sites)
{
RunTest(sites, 1);
RunTest(sites, 5);
RunTest(sites, 25);
RunTest(sites, 50);
RunTest(sites, 100);
RunTest(sites, 500);
RunTest(sites, 1000);
}
private void RunTest(string[] sites, int iterations, string description = "")
{
var action = GetAction();
var watch = new Stopwatch();
// Construct started tasks
Task<bool>[] tasks = new Task<bool>[sites.Count()];
watch.Start();
for(int j = 0; j < iterations; j++)
{
for (int i = 0; i < sites.Count(); i++)
{
tasks[i] = Task<bool>.Factory.StartNew(action, sites[i]);
}
}
try
{
Task.WaitAll(tasks);
}
catch (AggregateException e)
{
Console.WriteLine("\nThe following exceptions have been thrown by WaitAll()");
for (int j = 0; j < e.InnerExceptions.Count; j++)
{
Console.WriteLine("\n-------------------------------------------------\n{0}", e.InnerExceptions[j].ToString());
}
}
finally
{
watch.Stop();
Console.WriteLine("\"{0}|{1}|{2}\", ",sites.Count(), iterations, watch.Elapsed.TotalSeconds);
}
}
private Func<object, bool> GetAction()
{
baseUrl = baseUrl.Trim('/');
return (object obj) =>
{
var str = (string)obj;
var client = new RestClient(baseUrl);
client.Authenticator = new NtlmAuthenticator();
var request = new RestRequest(str, Method.GET);
request.AddHeader("Accept", "text/html");
var response = client.Execute(request);
return (response != null);
};
}