문제

나는 이와 같은 코드를 작성하고 조금 빠르고 더러운 타이밍을하고 있습니다.

var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
    b = DoStuff(s);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

분명히이 비트의 타이밍 코드를 Fancy-Schmancy .net 3.0 Lambda라고 부르는 방법이 있습니다. DoStuff(s) ~와 함께 DoSomethingElse(s)?

나는 그것이 a로 할 수 있다는 것을 안다 Delegate 그러나 나는 Lambda Way에 대해 궁금합니다.

도움이 되었습니까?

해결책

스톱워치 클래스를 확장하는 것은 어떻습니까?

public static class StopwatchExtensions
{
    public static long Time(this Stopwatch sw, Action action, int iterations)
    {
        sw.Reset();
        sw.Start(); 
        for (int i = 0; i < iterations; i++)
        {
            action();
        }
        sw.Stop();

        return sw.ElapsedMilliseconds;
    }
}

그런 다음 다음과 같이 부릅니다.

var s = new Stopwatch();
Console.WriteLine(s.Time(() => DoStuff(), 1000));

"반복"매개 변수를 생략하는 다른 오버로드를 추가하고 기본값 (1000) 으로이 버전을 호출 할 수 있습니다.

다른 팁

내가 사용했던 것은 다음과 같습니다.

public class DisposableStopwatch: IDisposable {
    private readonly Stopwatch sw;
    private readonly Action<TimeSpan> f;

    public DisposableStopwatch(Action<TimeSpan> f) {
        this.f = f;
        sw = Stopwatch.StartNew();
    }

    public void Dispose() {
        sw.Stop();
        f(sw.Elapsed);
    }
}

용법:

using (new DisposableStopwatch(t => Console.WriteLine("{0} elapsed", t))) {
  // do stuff that I want to measure
}

사용중인 클래스 (또는 기본 클래스)에 대한 확장 방법을 작성해 볼 수 있습니다.

나는 전화를 다음과 같습니다.

Stopwatch sw = MyObject.TimedFor(1000, () => DoStuff(s));

그런 다음 확장 방법 :

public static Stopwatch TimedFor(this DependencyObject source, Int32 loops, Action action)
{
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < loops; ++i)
{
    action.Invoke();
}
sw.Stop();

return sw;
}

종속성 OBJECT에서 파생되는 모든 객체는 이제 timedfor (..)를 호출 할 수 있습니다. ref params를 통해 반환 값을 제공하기 위해 함수를 쉽게 조정할 수 있습니다.

--

기능이 클래스 / 객체에 연결되기를 원하지 않으면 다음과 같은 작업을 수행 할 수 있습니다.

public class Timing
{
  public static Stopwatch TimedFor(Action action, Int32 loops)
  {
    var sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < loops; ++i)
    {
      action.Invoke();
    }
    sw.Stop();

    return sw;
  }
}

그런 다음 다음과 같이 사용할 수 있습니다.

Stopwatch sw = Timing.TimedFor(() => DoStuff(s), 1000);

실패하면,이 답변은 괜찮은 "일반적인"능력을 가지고있는 것처럼 보입니다.

대의원 또는 람다로 스톱워치 타이밍을 포장 하시겠습니까?

그만큼 StopWatch 수업은 필요하지 않습니다 Disposed 또는 Stopped 오류가 발생합니다. 따라서 가장 간단한 코드입니다 시각 약간 동작 ~이다

public partial class With
{
    public static long Benchmark(Action action)
    {
        var stopwatch = Stopwatch.StartNew();
        action();
        stopwatch.Stop();
        return stopwatch.ElapsedMilliseconds;
    }
}

샘플 호출 코드

public void Execute(Action action)
{
    var time = With.Benchmark(action);
    log.DebugFormat(“Did action in {0} ms.”, time);
}

나는 반복을 StopWatch 암호. 실행을 처리하는 다른 메소드 또는 확장자를 항상 만들 수 있습니다. N 반복.

public partial class With
{
    public static void Iterations(int n, Action action)
    {
        for(int count = 0; count < n; count++)
            action();
    }
}

샘플 호출 코드

public void Execute(Action action, int n)
{
    var time = With.Benchmark(With.Iterations(n, action));
    log.DebugFormat(“Did action {0} times in {1} ms.”, n, time);
}

확장 방법 버전은 다음과 같습니다

public static class Extensions
{
    public static long Benchmark(this Action action)
    {
        return With.Benchmark(action);
    }

    public static Action Iterations(this Action action, int n)
    {
        return () => With.Iterations(n, action);
    }
}

샘플 호출 코드

public void Execute(Action action, int n)
{
    var time = action.Iterations(n).Benchmark()
    log.DebugFormat(“Did action {0} times in {1} ms.”, n, time);
}

정적 방법과 확장 방법 (반복과 벤치 마크 결합)을 테스트했으며 예상 실행 시간의 델타는 <= 1ms입니다.

나는 얼마 전에 스톱워치를 래핑하여 액션을 사용하여 방법을 쉽게 프로파일하기 위해 간단한 코드 프로 필러 클래스를 썼습니다.http://www.improve.dk/blog/2008/04/16/profiling-code-the-easy-way

또한 Code MultithReaded를 쉽게 프로파일 할 수 있습니다. 다음 예제는 1-16 스레드로 액션 람다를 프로파일 링합니다.

static void Main(string[] args)
{
    Action action = () =>
    {
        for (int i = 0; i < 10000000; i++)
            Math.Sqrt(i);
    };

    for(int i=1; i<=16; i++)
        Console.WriteLine(i + " thread(s):\t" + 
            CodeProfiler.ProfileAction(action, 100, i));

    Console.Read();
}

한 가지 빠른 타이밍이 필요하다고 가정하면 사용하기 쉽습니다.

  public static class Test {
    public static void Invoke() {
        using( SingleTimer.Start )
            Thread.Sleep( 200 );
        Console.WriteLine( SingleTimer.Elapsed );

        using( SingleTimer.Start ) {
            Thread.Sleep( 300 );
        }
        Console.WriteLine( SingleTimer.Elapsed );
    }
}

public class SingleTimer :IDisposable {
    private Stopwatch stopwatch = new Stopwatch();

    public static readonly SingleTimer timer = new SingleTimer();
    public static SingleTimer Start {
        get {
            timer.stopwatch.Reset();
            timer.stopwatch.Start();
            return timer;
        }
    }

    public void Stop() {
        stopwatch.Stop();
    }
    public void Dispose() {
        stopwatch.Stop();
    }

    public static TimeSpan Elapsed {
        get { return timer.stopwatch.Elapsed; }
    }
}

Lambda에 전달하려는 다양한 매개 변수 사례를 다루기 위해 여러 가지 방법을 과부하 할 수 있습니다.

public static Stopwatch MeasureTime<T>(int iterations, Action<T> action, T param)
{
    var sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < iterations; i++)
    {
        action.Invoke(param);
    }
    sw.Stop();

    return sw;
}

public static Stopwatch MeasureTime<T, K>(int iterations, Action<T, K> action, T param1, K param2)
{
    var sw = new Stopwatch();
    sw.Start();
    for (int i = 0; i < iterations; i++)
    {
        action.Invoke(param1, param2);
    }
    sw.Stop();

    return sw;
}

또는 값을 반환 해야하는 경우 FUNC 대의원을 사용할 수 있습니다. 각 반복이 고유 한 값을 사용해야하는 경우 배열 (또는 그 이상)의 매개 변수를 전달할 수도 있습니다.

나에게 확장은 INT에 대해 조금 더 직관적 인 느낌이 들기 때문에 더 이상 스톱워치를 인스턴스화하거나 재설정에 대해 걱정할 필요가 없습니다.

그래서 당신은 다음과 같습니다.

static class BenchmarkExtension {

    public static void Times(this int times, string description, Action action) {
        Stopwatch watch = new Stopwatch();
        watch.Start();
        for (int i = 0; i < times; i++) {
            action();
        }
        watch.Stop();
        Console.WriteLine("{0} ... Total time: {1}ms ({2} iterations)", 
            description,  
            watch.ElapsedMilliseconds,
            times);
    }
}

샘플 사용으로 :

var randomStrings = Enumerable.Range(0, 10000)
    .Select(_ => Guid.NewGuid().ToString())
    .ToArray();

50.Times("Add 10,000 random strings to a Dictionary", 
    () => {
        var dict = new Dictionary<string, object>();
        foreach (var str in randomStrings) {
            dict.Add(str, null);
        }
    });

50.Times("Add 10,000 random strings to a SortedList",
    () => {
        var list = new SortedList<string, object>();
        foreach (var str in randomStrings) {
            list.Add(str, null);
        }
    });

샘플 출력 :

Add 10,000 random strings to a Dictionary ... Total time: 144ms (50 iterations)
Add 10,000 random strings to a SortedList ... Total time: 4088ms (50 iterations)

Vance Morrison (.NET의 공연 친구 중 하나)의 CodeTimer 클래스를 사용하고 싶습니다.

그는 자신의 블로그 제목의 ""에 ""게시물을 작성했습니다.관리 코드를 빠르게 측정하고 Easiliy : CodeTimers".

MultiSampleCodetimer와 같은 멋진 물건이 포함됩니다. 평균 및 표준 편차를 자동으로 계산하고 결과를 인쇄하기가 매우 쉽습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top