如何在C#中多次使用计时器(StopWatch)?

11

我有一段短代码可以执行不同的操作,我想测量每个操作所需的时间。在这里我阅读了关于Stopwatch类的文章,并希望优化我的时间测量方法。 我的函数调用了5个其他函数,并且我想在不声明变量的情况下测量每个函数的执行时间。


我的函数调用了5个其他函数,并且我想在不声明变量的情况下测量每个函数的执行时间。
stopwatch sw1 = new stopwatch();
stopwatch sw2 = new stopwatch();
etc..

我的函数长这样:

public bool func()
{
 ....
 func1()
 func2()
 ....
 ....
 func5()
}

有没有办法使用一个秒表实例来测量时间?

谢谢!!

5个回答

23

使用委托将方法作为参数传递给函数。

这里我使用了Action委托,因为指定的方法不返回值。

如果您的方法具有返回类型或参数,则可以使用Function委托进行相应修改。

    static void Main(string[] args)
    {
        Console.WriteLine("Method 1 Time Elapsed (ms): {0}", TimeMethod(Method1));
        Console.WriteLine("Method 2 Time Elapsed (ms): {0}", TimeMethod(Method2));
    }

    static long TimeMethod(Action methodToTime)
    {
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        methodToTime();
        stopwatch.Stop();
        return stopwatch.ElapsedMilliseconds;
    }

    static void Method1()
    {
        for (int i = 0; i < 100000; i++)
        {
            for (int j = 0; j < 1000; j++)
            {
            }
        }
    }

    static void Method2()
    {
        for (int i = 0; i < 5000; i++)
        {
        }
    }
}

通过使用这个,您可以传递任何想要的方法。

希望这有所帮助!


14

你需要的是 Stopwatch 类的 Restart 函数,类似于以下内容:

public bool func()
{
    var stopwatch = Stopwatch.StartNew();

    func1();

    Debug.WriteLine(stopwatch.ElapsedMilliseconds);

    stopwatch.Restart();

    func5();

    Debug.WriteLine(stopwatch.ElapsedMilliseconds);
}

6

是的,请尝试这个:

    void func1()
    {
        Stopwatch sw = new Stopwatch();
        sw.Start();
        func1();
        sw.Stop();
        Console.Write(sw.Elapsed);

        sw.Restart();
        func2();
        sw.Stop();
        Console.Write(sw.Elapsed);
    }

在这种情况下,编写sw.Restart和sw.Start有什么区别吗? - user1386966
3
使用“重启”功能停止当前时间间隔的测量,并开始新的时间间隔测量(MSDN)。重启将清除经过的时间。 - oakio

2
您可以使用这个小类:
public class PolyStopwatch
{
    readonly Dictionary<string, long> counters;

    readonly Stopwatch stopwatch;

    string currentLabel;

    public PolyStopwatch()
    {
        stopwatch = new Stopwatch();
        counters = new Dictionary<string, long>();
    }

    public void Start(string label)
    {
        if (currentLabel != null) Stop();

        currentLabel = label;
        if (!counters.ContainsKey(label))
            counters.Add(label, 0);
        stopwatch.Restart();
    }

    public void Stop()
    {
        if (currentLabel == null)
            throw new InvalidOperationException("No counter started");

        stopwatch.Stop();
        counters[currentLabel] += stopwatch.ElapsedMilliseconds;
        currentLabel = null;
    }

    public void Print()
    {
        if (currentLabel != null) Stop();

        long totalTime = counters.Values.Sum();
        foreach (KeyValuePair<string, long> kvp in counters)
            Debug.Print("{0,-40}: {1,8:N0} ms ({2:P})", kvp.Key, kvp.Value, (double) kvp.Value / totalTime);
        Debug.WriteLine(new string('-', 62));
        Debug.Print("{0,-40}: {1,8:N0} ms", "Total time", totalTime);
    }
}

使用方法如下:

var ps = new PolyStopwatch();

ps.Start("Method1");
Method1();
ps.Stop();

// other code...

ps.Start("Method2");
Method2();
ps.Stop();

ps.Print();

如果调用彼此跟随,您可以省略Stop()。
ps.Start("Method1");
Method1();
ps.Start("Method2");
Method2();
ps.Print();

使用循环可以很好地运作:

for(int i = 0; i < 10000; i++)
{
    ps.Start("Method1");
    Method1();
    ps.Start("Method2");
    Method2();
}
ps.Print();

1

我使用:

void MyFunc()
    {
        Watcher watcher = new Watcher();
        //Some call
        HightLoadFunc();
        watcher.Tick("My high load tick 1");

        SecondFunc();
        watcher.Tick("Second tick");

        Debug.WriteLine(watcher.Result());
        //Total: 0.8343141s; My high load tick 1: 0.4168064s; Second tick: 0.0010215s;
    }

class Watcher
{
    DateTime start;
    DateTime endTime;

    List<KeyValuePair<DateTime, string>> times = new List<KeyValuePair<DateTime, string>>();

    public Watcher()
    {
        start = DateTime.Now;
        times.Add(new KeyValuePair<DateTime, string>(start, "start"));
        endTime = start;
    }

    public void Tick(string message)
    {
        times.Add(new KeyValuePair<DateTime, string>(DateTime.Now, message));
    }

    public void End()
    {
        endTime = DateTime.Now;
    }

    public string Result(bool useNewLine = false)
    {
        string result = "";
        if (endTime == start)
            endTime = DateTime.Now;

        var total = (endTime - start).TotalSeconds;
        result = $"Total: {total}s;";

        if (times.Count <2)
            return result + " Not another times.";
        else 
            for(int i=1; i<times.Count; i++)
            {
                if (useNewLine) result += Environment.NewLine;
                var time = (times[i].Key - times[i - 1].Key).TotalSeconds;
                var m = times[i];
                result += $" {m.Value}: {time}s;";
            }

        return result;
    }
}

这是一个很棒的方法! - Freddy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接