9

渡された(任意のタイプの)メソッドの実行時間を測定することを目的として、非常に単純なユーティリティクラスを作成しています。

私の場合Membership.ValidateUser(model.UserName, model.Password)は bool を返すため、例外が発生します。

可能であれば、このタイプのユーティリティ クラスと、それを修正する方法に関するコードのサンプルを書きたいと思います。アクションの代わりにダイナミックを使用するのは理にかなっていますか?

Tracing.Log(Membership.ValidateUser(model.UserName, model.Password), "Membership.ValidateUser");

public static class Tracing
        {
            public static void Log(Action action, string message)
            {
                // Default details for the Log
                string sSource = "TRACE";
                string sLog = "Application";

                // Create the Log
                if (!EventLog.SourceExists(sSource))
                    EventLog.CreateEventSource(sSource, sLog);

                // Measure time Elapsed for an Action
                Stopwatch stopwatch = Stopwatch.StartNew();
                action();
                stopwatch.Stop();
                TimeSpan timeElapsed = stopwatch.Elapsed;

                // Write the Log
                EventLog.WriteEntry(sSource, "TIME-ELAPSED: " + timeElapsed .ToString() + message, EventLogEntryType.Warning, 234);
            }
        }
4

4 に答える 4

8

現在のコードは実行を試み、その結果をメソッド引数としてValidateUser使用しようとしています。最初に を実行せずにアクションを渡したい。ValidateUser

メソッド呼び出しをラムダ式を使用してデリゲートを作成するように変換するだけです。

Tracing.Log(() => Membership.ValidateUser(model.UserName, model.Password), 
            "Membership.ValidateUser");

(動的型付けはこれにまったく影響しません。)

かなり長いメソッド呼び出しでない限り、単一のメソッド実行のタイミングを計ると、非常にノイズの多い結果が得られることが多いことに注意してください。通常、1 つのメソッドのベンチマークを行うには、そのメソッドの実行にかなりの時間を費やすまで、そのメソッドを何度も実行する必要があります。を使用Stopwatchすると役立ちますが、メソッドが完了するまでに必要なティック数が非常に少なく、スレッドがプリエンプトされると、結果に不均衡な影響を与える可能性があるという事実を乗り越えることはできません。

編集:これを純粋にベンチマークに使用することを想定しています。実際のアプリケーションでこのトレースを実行しようとしている場合は、より侵襲性の低いアプローチが必要になります。たとえば、 Mini-MVC-Profilerを見てください。

于 2013-03-13T12:33:31.077 に答える
0

気分を害するつもりはありませんが、あなたの設計アプローチは私には後退しているように見えます。あなたのビジネス目標は、コード操作のタイミングよりもユーザーの検証にあると思います。それが間違っている場合は、私を無視してください。:)

私があなただったら、その逆ではなく、タイミング/トレース クラスを検証に挿入します。依存性注入はさまざまな方法 (フレームワークの 1 つまたは単純なコンストラクター注入) で使用でき、提供されている場合はそれを使用してタイミングを実行できます。

HTH

于 2013-03-13T12:35:57.303 に答える
0

測定されるメソッドを変更できる場合は、作成時にタイマーを開始し、廃棄時に停止するクラスを導入できます。また、何らかのしきい値を超えると、ログ メッセージが作成されます

使用法は次のとおりです。

using(var tm = new TimeMeasurementThreshold(TimeSpan.FromSeconds(1),"Sending mail block",logger)){
 // measured code here 
}

public class TimeMeasurementThreshold : IDisposable
    {
        private readonly Logger logger;

        private readonly TimeSpan thresholdTime;

        private readonly string codeBlockName;

        private readonly TimeMeasurement timeMeasurement;

        public TimeMeasurementThreshold(TimeSpan thresholdTime, string codeBlockName, Logger logger)
        {
            this.logger = logger;
            this.thresholdTime = thresholdTime;
            this.codeBlockName = codeBlockName;

            timeMeasurement = new TimeMeasurement();
        }

        public void Dispose()
        {
            TimeSpan elapsed = timeMeasurement.Elapsed;

            if (elapsed >= thresholdTime)
            {
                logger.Debug("{0} execution time is {1:N0}ms", codeBlockName, elapsed.TotalMilliseconds);
            }
        }
    }
于 2013-03-13T12:36:57.653 に答える
0

ラムダを使用して、別のメソッドに渡すアクションの結果を簡単に割り当てることができます。次に例を示します。

using System;

namespace Demo
{
    public static class Program
    {
        private static void Main(string[] args)
        {
            bool result = false;

            Tracing.Log(() =>
            {
                result = test("");  // Assign to result.
            }, "Message");

            Console.WriteLine(result);
        }

        private static bool test(string value)
        {
            return string.IsNullOrEmpty(value);
        }
    }

    public static class Tracing
    {
        public static void Log(Action action, string message)
        {
            action();
            Console.WriteLine(message);
        }
    }
}
于 2013-03-13T12:39:40.070 に答える