I'm writing code like this, doing a little quick and dirty timing:
我在写这样的代码,做一些快速和不准确的时间:
var sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
b = DoStuff(s);
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Surely there's a way to call this bit of timing code as a fancy-schmancy .NET 3.0 lambda rather than (God forbid) cutting and pasting it a few times and replacing the DoStuff(s)
with DoSomethingElse(s)
?
当然,有一种方法可以将这段计时代码称为一个假想的。net 3.0 lambda,而不是(上帝不允许)将它剪切和粘贴几次,并用DoSomethingElse(s)替换dosomething (s)?
I know it can be done as a Delegate
but I'm wondering about the lambda way.
我知道它可以作为一个委托来完成但是我想知道lambda表达式。
9 个解决方案
#1
127
How about extending the Stopwatch 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;
}
}
Then call it like this:
然后这样称呼它:
var s = new Stopwatch();
Console.WriteLine(s.Time(() => DoStuff(), 1000));
You could add another overload which omits the "iterations" parameter and calls this version with some default value (like 1000).
您可以添加另一个忽略“迭代”参数的重载,并使用一些默认值(如1000)调用这个版本。
#2
27
Here's what I've been using:
以下是我一直在使用的:
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);
}
}
Usage:
用法:
using (new DisposableStopwatch(t => Console.WriteLine("{0} elapsed", t))) {
// do stuff that I want to measure
}
#3
12
You could try writing an extension method for whatever class you're using (or any base class).
您可以尝试为您正在使用的任何类(或任何基类)编写扩展方法。
I would have the call look like:
我会让电话看起来是这样的:
Stopwatch sw = MyObject.TimedFor(1000, () => DoStuff(s));
Then the extension method:
然后扩展方法:
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;
}
Any object deriving from DependencyObject can now call TimedFor(..). The function can easily be adjusted to provide return values via ref params.
任何从DependencyObject派生的对象现在都可以调用TimedFor(.. .)。该函数可以通过ref参数轻松调整以提供返回值。
--
- - -
If you didn't want the functionality to be tied to any class / object you could do something like:
如果您不希望功能与任何类/对象绑定,您可以做以下事情:
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;
}
}
Then you could use it like:
然后你可以这样使用它:
Stopwatch sw = Timing.TimedFor(() => DoStuff(s), 1000);
Failing that, this answer looks like it has some decent "generic" ability:
如果做不到这一点,这个答案看起来似乎有一些不错的“通用”能力:
Wrapping StopWatch timing with a delegate or lambda?
用委托或lambda来结束秒表计时?
#4
7
I wrote a simple CodeProfiler class some time ago that wrapped Stopwatch to easily profile a method using an Action: http://www.improve.dk/blog/2008/04/16/profiling-code-the-easy-way
不久前,我编写了一个简单的代码分析器类,它封装了秒表,以便使用以下操作来轻松地配置方法:http://www.improve.dk/blog/2008/04/16/profiling-code-the-easy-way
It'll also easily allow you to profile the code multithreaded. The following example will profile the action lambda with 1-16 threads:
它还可以方便地让您对代码进行多线程配置。下面的示例将使用1-16个线程对动作lambda进行配置:
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();
}
#5
6
The StopWatch
class does not need to be Disposed
or Stopped
on error. So, the simplest code to time some action is
秒表类不需要在错误时被处理或停止。最简单的代码是
public partial class With
{
public static long Benchmark(Action action)
{
var stopwatch = Stopwatch.StartNew();
action();
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
}
Sample calling code
示例调用代码
public void Execute(Action action)
{
var time = With.Benchmark(action);
log.DebugFormat(“Did action in {0} ms.”, time);
}
I don't like the idea of including the iterations into the StopWatch
code. You can always create another method or extension that handles executing N
iterations.
我不喜欢将迭代包含到秒表代码中。您总是可以创建另一个方法或扩展来处理执行N次迭代。
public partial class With
{
public static void Iterations(int n, Action action)
{
for(int count = 0; count < n; count++)
action();
}
}
Sample calling code
示例调用代码
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);
}
Here are the extension method versions
这里是扩展方法的版本。
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);
}
}
And sample calling code
和示例调用代码
public void Execute(Action action, int n)
{
var time = action.Iterations(n).Benchmark()
log.DebugFormat(“Did action {0} times in {1} ms.”, n, time);
}
I tested the static methods and extension methods (combining iterations and benchmark) and the delta of expected execution time and real execution time is <= 1 ms.
我测试了静态方法和扩展方法(结合迭代和基准),期望执行时间和实际执行时间的增量为<= 1ms。
#6
4
Assuming you just need a quick timing of one thing this is easy to use.
假设你只需要对一件事做一个快速的定时,这很容易使用。
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; }
}
}
#7
2
For me the extension feels a little bit more intuitive on int, you no longer need to instantiate a Stopwatch or worry about resetting it.
对我来说,扩展在int上感觉更直观一些,您不再需要实例化秒表或担心重新设置它。
So you have:
所以你有:
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);
}
}
With the sample usage of:
样本用途为:
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);
}
});
Sample output:
样例输出:
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)
#8
1
You can overload a number of methods to cover various cases of parameters you might want to pass to the lambda:
您可以重载许多方法,以覆盖您可能希望传递给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;
}
Alternatively, you can use the Func delegate if they must return a value. You can also pass in an array (or more) of parameters if each iteration must use a unique value.
另外,如果Func委托必须返回一个值,也可以使用它。如果每次迭代都必须使用唯一值,还可以传入一个参数数组(或多个)。
#9
1
I like to use the CodeTimer classes from Vance Morrison (one of the performance dudes from .NET).
我喜欢使用Vance Morrison的CodeTimer类(来自。net的性能伙伴之一)。
He made a post on on his blog titled "Measuring managed code quickly and easiliy: CodeTimers".
他在自己的博客上发表了一篇文章,标题是“快速、轻松地测量托管代码:codetimer”。
It includes cool stuff such as a MultiSampleCodeTimer. It does automatic calculation of the mean and standard deviation and its also very easy to print out your results.
它包括一些很酷的东西,比如多采样码计时器。它可以自动计算均值和标准差,也很容易打印出结果。
#1
127
How about extending the Stopwatch 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;
}
}
Then call it like this:
然后这样称呼它:
var s = new Stopwatch();
Console.WriteLine(s.Time(() => DoStuff(), 1000));
You could add another overload which omits the "iterations" parameter and calls this version with some default value (like 1000).
您可以添加另一个忽略“迭代”参数的重载,并使用一些默认值(如1000)调用这个版本。
#2
27
Here's what I've been using:
以下是我一直在使用的:
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);
}
}
Usage:
用法:
using (new DisposableStopwatch(t => Console.WriteLine("{0} elapsed", t))) {
// do stuff that I want to measure
}
#3
12
You could try writing an extension method for whatever class you're using (or any base class).
您可以尝试为您正在使用的任何类(或任何基类)编写扩展方法。
I would have the call look like:
我会让电话看起来是这样的:
Stopwatch sw = MyObject.TimedFor(1000, () => DoStuff(s));
Then the extension method:
然后扩展方法:
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;
}
Any object deriving from DependencyObject can now call TimedFor(..). The function can easily be adjusted to provide return values via ref params.
任何从DependencyObject派生的对象现在都可以调用TimedFor(.. .)。该函数可以通过ref参数轻松调整以提供返回值。
--
- - -
If you didn't want the functionality to be tied to any class / object you could do something like:
如果您不希望功能与任何类/对象绑定,您可以做以下事情:
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;
}
}
Then you could use it like:
然后你可以这样使用它:
Stopwatch sw = Timing.TimedFor(() => DoStuff(s), 1000);
Failing that, this answer looks like it has some decent "generic" ability:
如果做不到这一点,这个答案看起来似乎有一些不错的“通用”能力:
Wrapping StopWatch timing with a delegate or lambda?
用委托或lambda来结束秒表计时?
#4
7
I wrote a simple CodeProfiler class some time ago that wrapped Stopwatch to easily profile a method using an Action: http://www.improve.dk/blog/2008/04/16/profiling-code-the-easy-way
不久前,我编写了一个简单的代码分析器类,它封装了秒表,以便使用以下操作来轻松地配置方法:http://www.improve.dk/blog/2008/04/16/profiling-code-the-easy-way
It'll also easily allow you to profile the code multithreaded. The following example will profile the action lambda with 1-16 threads:
它还可以方便地让您对代码进行多线程配置。下面的示例将使用1-16个线程对动作lambda进行配置:
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();
}
#5
6
The StopWatch
class does not need to be Disposed
or Stopped
on error. So, the simplest code to time some action is
秒表类不需要在错误时被处理或停止。最简单的代码是
public partial class With
{
public static long Benchmark(Action action)
{
var stopwatch = Stopwatch.StartNew();
action();
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
}
Sample calling code
示例调用代码
public void Execute(Action action)
{
var time = With.Benchmark(action);
log.DebugFormat(“Did action in {0} ms.”, time);
}
I don't like the idea of including the iterations into the StopWatch
code. You can always create another method or extension that handles executing N
iterations.
我不喜欢将迭代包含到秒表代码中。您总是可以创建另一个方法或扩展来处理执行N次迭代。
public partial class With
{
public static void Iterations(int n, Action action)
{
for(int count = 0; count < n; count++)
action();
}
}
Sample calling code
示例调用代码
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);
}
Here are the extension method versions
这里是扩展方法的版本。
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);
}
}
And sample calling code
和示例调用代码
public void Execute(Action action, int n)
{
var time = action.Iterations(n).Benchmark()
log.DebugFormat(“Did action {0} times in {1} ms.”, n, time);
}
I tested the static methods and extension methods (combining iterations and benchmark) and the delta of expected execution time and real execution time is <= 1 ms.
我测试了静态方法和扩展方法(结合迭代和基准),期望执行时间和实际执行时间的增量为<= 1ms。
#6
4
Assuming you just need a quick timing of one thing this is easy to use.
假设你只需要对一件事做一个快速的定时,这很容易使用。
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; }
}
}
#7
2
For me the extension feels a little bit more intuitive on int, you no longer need to instantiate a Stopwatch or worry about resetting it.
对我来说,扩展在int上感觉更直观一些,您不再需要实例化秒表或担心重新设置它。
So you have:
所以你有:
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);
}
}
With the sample usage of:
样本用途为:
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);
}
});
Sample output:
样例输出:
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)
#8
1
You can overload a number of methods to cover various cases of parameters you might want to pass to the lambda:
您可以重载许多方法,以覆盖您可能希望传递给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;
}
Alternatively, you can use the Func delegate if they must return a value. You can also pass in an array (or more) of parameters if each iteration must use a unique value.
另外,如果Func委托必须返回一个值,也可以使用它。如果每次迭代都必须使用唯一值,还可以传入一个参数数组(或多个)。
#9
1
I like to use the CodeTimer classes from Vance Morrison (one of the performance dudes from .NET).
我喜欢使用Vance Morrison的CodeTimer类(来自。net的性能伙伴之一)。
He made a post on on his blog titled "Measuring managed code quickly and easiliy: CodeTimers".
他在自己的博客上发表了一篇文章,标题是“快速、轻松地测量托管代码:codetimer”。
It includes cool stuff such as a MultiSampleCodeTimer. It does automatic calculation of the mean and standard deviation and its also very easy to print out your results.
它包括一些很酷的东西,比如多采样码计时器。它可以自动计算均值和标准差,也很容易打印出结果。