Завершение сеанса StopWatch с помощью делегата или lambda?

Я пишу такой код, делая несколько быстрых и грязных сроков:

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

Разумеется, есть способ назвать этот бит временного кода как фэнтезийный .NET 3.0 lambda, а не (не дай бог) резать и вставлять его несколько раз и заменять DoStuff(s) DoSomethingElse(s) ?

Я знаю, что это может быть сделано в качестве Delegate но мне интересно, как lambda-образ.

Как насчет расширения classа секундомера?

 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 f; public DisposableStopwatch(Action 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 } 

Вы можете попробовать написать метод расширения для любого classа, который вы используете (или любого базового classа).

Я бы назвал:

 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; } 

Любой объект, происходящий из DependencyObject, теперь может вызывать TimedFor (..). Функция может быть легко отрегулирована для обеспечения возвращаемых значений через ref params.

-

Если вы не хотите, чтобы функциональность была привязана к любому classу / объекту, вы могли бы сделать что-то вроде:

 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 с помощью делегата или lambda?

Некоторое время назад я написал простой class CodeProfiler, который завербовал Секундомер, чтобы легко профилировать метод с помощью Action: http://www.improve.dk/blog/2008/04/16/profiling-code-the-easy-way

Он также легко позволит вам профилировать код многопоточным. В следующем примере будет описано действие lambda с 1-16 streamами:

 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(); } 

Класс 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); } 

Я тестировал статические методы и методы расширения (объединение итераций и тестов), а дельта ожидаемого времени выполнения и реального времени выполнения <= 1 мс.

Предполагая, что вам просто нужно быстро выбрать одну вещь, это легко использовать.

  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; } } } 

Для меня расширение кажется немного интуитивным в 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(); foreach (var str in randomStrings) { dict.Add(str, null); } }); 50.Times("Add 10,000 random strings to a SortedList", () => { var list = new SortedList(); 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) 

Вы можете перегрузить ряд методов, чтобы охватить различные случаи параметров, которые вы, возможно, захотите передать в lambda:

 public static Stopwatch MeasureTime(int iterations, Action 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(int iterations, Action 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, если они должны вернуть значение. Вы также можете передать массив (или больше) параметров, если каждая итерация должна использовать уникальное значение.

Мне нравится использовать classы CodeTimer из Vance Morrison (один из разработчиков производительности .NET).

Он сделал запись в своем блоге под названием « Измерение управляемого кода быстро и легко: CodeTimers ».

Он включает classные вещи, такие как MultiSampleCodeTimer. Он выполняет автоматический расчет среднего и стандартного отклонения, а также очень легко распечатать ваши результаты.

  • Maven. lambda-выражения не поддерживаются в источнике 1.5
  • Лямбда-выражения как параметры шаблона classа
  • Сортировка списка с использованием Lambda / Linq для объектов
  • Захват ссылки по ссылке в C ++ 11 lambda
  • Выражение lambda и общий метод
  • Использование адаптеров Boost с C ++ 11 lambdas
  • Получить имя и тип свойства, используя выражение lambda
  • Java 8 группировка с использованием пользовательского коллектора?
  • Невозможно преобразовать lambda-выражение для ввода «string», потому что это не тип делегата
  • Объединение двух выражений (выражение <Func >)
  • Очень запутано в выводе типа Java 8 Comparator
  • Interesting Posts

    Время работы накопителей SSD

    Самый простой способ получить идентификатор файла из URL-адреса в скрипте Google Apps

    ITunes сохраняет исходные файлы на новом внешнем диске

    Как создать URL-адрес REST без глаголов?

    Объявления переменной C после заголовка функции в определении

    Как использовать reflection для вызова общего метода?

    Должен ли я использовать отдельные экземпляры ScriptEngine и CompiledScript для каждого streamа?

    Как создавать резервные копии символических путей ссылок?

    Как отрегулировать ведущее / завершающее пробелы стандартным образом?

    Измерение высоты текста на Canvas (Android)

    Вырез инструмента JFreechart над аннотацией формы

    Когда использовать интерфейс вместо абстрактного classа и наоборот?

    Добавить текст в начало каждой другой строки в Notepad ++

    Как получить документы в каталоге Android, которые PhoneGap увидит

    Notepad ++. Как заменить разные символы соответствующими буквами одновременно?

    Давайте будем гением компьютера.