C# 查找方法的执行时间

C# 查找方法的执行时间,c#,.net,C#,.net,我正在为我的大学做一个图像隐写术项目。我已经完成了这个项目,并保留了几种不同的算法来隐藏图像中的数据 我想问的是,在C#中是否有任何方法可以找到程序中两点之间的执行/运行时间。 比如说 //Some Code //Code to start recording the time. hideDataUsingAlgorithm(); //Code to stop recording and get the time of execution of the above function. 我想这

我正在为我的大学做一个图像隐写术项目。我已经完成了这个项目,并保留了几种不同的算法来隐藏图像中的数据

我想问的是,在C#中是否有任何方法可以找到程序中两点之间的执行/运行时间。 比如说

//Some Code
//Code to start recording the time.
hideDataUsingAlgorithm();
//Code to stop recording and get the time of execution of the above function. 
我想这样做是为了说明简单(耗时更少)和更高效但耗时的算法(使用相同的数据和相同的图像)之间的区别。我有大约10种不同的彩色和灰度图像算法

没有多线程,所以这不会是一个问题。只有一个主线程。

和类是两个可以很好地实现更高分辨率和直接使用的线程

另见:

  • 您可以使用类:


    这是秒表的一种有用的扩展方法:

    public static class StopwatchExt
    {
        public static string GetTimeString(this Stopwatch stopwatch, int numberofDigits = 1)
        {
            double time = stopwatch.ElapsedTicks / (double)Stopwatch.Frequency;
            if (time > 1)
                return Math.Round(time, numberofDigits) + " s";
            if (time > 1e-3)
                return Math.Round(1e3 * time, numberofDigits) + " ms";
            if (time > 1e-6)
                return Math.Round(1e6 * time, numberofDigits) + " µs";
            if (time > 1e-9)
                return Math.Round(1e9 * time, numberofDigits) + " ns";
            return stopwatch.ElapsedTicks + " ticks";
        }
    }
    
    像这样使用它:

    Stopwatch stopwatch = Stopwatch.StartNew();
    //Call your method here
    stopwatch.Stop();
    Console.WriteLine(stopwatch.GetTimeString());
    

    您可以向测试方法声明一个委托,并使用以下扩展方法之一执行它N次。根据打印到控制台的传递的格式字符串:

    • 首次通话时间
    • 经过的时间
    • 呼叫频率
    这些都是有用的值。扩展方法使用秒表获得最高精度

    Action acc = hideDataUsingAlgorithm;
    acc.Profile(100*1000, "Method did run {runs} times in {time}s, Frequency: {frequency}");
    
    还要检查您可以使用的启动效果

    acc.ProfileFirst(100*1000, "First call {0}s", "Method did run {runs} times in {time}s, Frequency: {frequency}");
    
    通过这种方式,如果所讨论的方法不是空方法,那么您可以轻松地检查您的方法,因为委托调用与方法调用相当,因此空方法会扭曲计时。最初的想法是写在博客上的

    对于更深入的调用时间分析,分析器也非常有用。您应该尝试使用这些工具来诊断更棘手的问题

    using System;
    using System.Globalization;
    using System.Diagnostics;
    
    namespace PerformanceTester
    {
       /// <summary>
       /// Helper class to print out performance related data like number of runs, elapsed time and frequency
       /// </summary>
       public static class Extension
       {
           static NumberFormatInfo myNumberFormat;
    
           static NumberFormatInfo NumberFormat
           {
               get
               {
                   if (myNumberFormat == null)
                   {
                       var local = new CultureInfo("en-us", false).NumberFormat;
                       local.NumberGroupSeparator = " "; // set space as thousand separator
                       myNumberFormat = local; // make a thread safe assignment with a fully initialized variable
                   }
                   return myNumberFormat;
               }
           }
    
           /// <summary>
           /// Execute the given function and print the elapsed time to the console.
           /// </summary>
           /// <param name="func">Function that returns the number of iterations.</param>
           /// <param name="format">Format string which can contain {runs} or {0},{time} or {1} and {frequency} or {2}.</param>
           public static void Profile(this Func<int> func, string format)
           {
    
               Stopwatch watch = Stopwatch.StartNew();
               int runs = func();  // Execute function and get number of iterations back
               watch.Stop();
    
               string replacedFormat = format.Replace("{runs}", "{3}")
                                             .Replace("{time}", "{4}")
                                             .Replace("{frequency}", "{5}");
    
               // get elapsed time back
               float sec = watch.ElapsedMilliseconds / 1000.0f;
               float frequency = runs / sec; // calculate frequency of the operation in question
    
               try
               {
                   Console.WriteLine(replacedFormat,
                                       runs,  // {0} is the number of runs
                                       sec,   // {1} is the elapsed time as float
                                       frequency, // {2} is the call frequency as float
                                       runs.ToString("N0", NumberFormat),  // Expanded token {runs} is formatted with thousand separators
                                       sec.ToString("F2", NumberFormat),   // expanded token {time} is formatted as float in seconds with two digits precision
                                       frequency.ToString("N0", NumberFormat)); // expanded token {frequency} is formatted as float with thousands separators
               }
               catch (FormatException ex)
               {
                   throw new FormatException(
                       String.Format("The input string format string did contain not an expected token like "+
                                     "{{runs}}/{{0}}, {{time}}/{{1}} or {{frequency}}/{{2}} or the format string " +
                                     "itself was invalid: \"{0}\"", format), ex);
               }
           }
    
           /// <summary>
           /// Execute the given function n-times and print the timing values (number of runs, elapsed time, call frequency)
           /// to the console window.
           /// </summary>
           /// <param name="func">Function to call in a for loop.</param>
           /// <param name="runs">Number of iterations.</param>
           /// <param name="format">Format string which can contain {runs} or {0},{time} or {1} and {frequency} or {2}.</param>
           public static void Profile(this Action func, int runs, string format)
           {
               Func<int> f = () =>
               {
                   for (int i = 0; i < runs; i++)
                   {
                       func();
                   }
                   return runs;
               };
               f.Profile(format);
           }
    
           /// <summary>
           /// Call a function in a for loop n-times. The first function call will be measured independently to measure
           /// first call effects.
           /// </summary>
           /// <param name="func">Function to call in a loop.</param>
           /// <param name="runs">Number of iterations.</param>
           /// <param name="formatFirst">Format string for first function call performance.</param>
           /// <param name="formatOther">Format string for subsequent function call performance.</param>
           /// <remarks>
           /// The format string can contain {runs} or {0},{time} or {1} and {frequency} or {2}.
           /// </remarks>
           public static void ProfileWithFirst(this Action func, int runs, string formatFirst, string formatOther)
           {
               func.Profile(1, formatFirst);
               func.Profile(runs - 1, formatOther);
           }
       }
    }
    
    使用系统;
    利用制度全球化;
    使用系统诊断;
    命名空间性能测试程序
    {
    /// 
    ///Helper类打印与性能相关的数据,如运行次数、运行时间和频率
    /// 
    公共静态类扩展
    {
    静态数字格式myNumberFormat;
    静态数字格式信息数字格式
    {
    得到
    {
    如果(myNumberFormat==null)
    {
    var local=新文化信息(“en-us”,false);
    local.NumberGroupSeparator=“;//将空格设置为千位分隔符
    myNumberFormat=local;//使用完全初始化的变量进行线程安全赋值
    }
    返回myNumberFormat;
    }
    }
    /// 
    ///执行给定的函数并将经过的时间打印到控制台。
    /// 
    ///返回迭代次数的函数。
    ///格式字符串,可以包含{runs}或{0}、{time}或{1}和{frequency}或{2}。
    公共静态无效配置文件(此函数,字符串格式)
    {
    秒表=Stopwatch.StartNew();
    int runs=func();//执行函数并返回迭代次数
    看,停;
    string replacedFormat=format.Replace(“{runs}”,“{3}”)
    .Replace(“{time},“{4}”)
    .替换(“{frequency},“{5}”);
    //返回经过的时间
    浮点数秒=watch.elapsedmillyses/1000.0f;
    float frequency=runs/sec;//计算相关操作的频率
    尝试
    {
    Console.WriteLine(替换格式,
    runs,//{0}是运行数
    秒,//{1}是作为浮点的经过时间
    frequency,//{2}是作为float的调用频率
    ToString(“N0”,NumberFormat),//扩展标记{runs}用千个分隔符格式化
    sec.ToString(“F2”,NumberFormat),//扩展标记{time}的格式为秒浮点,精度为两位数
    ToString(“N0”,NumberFormat));//扩展标记{frequency}的格式为带有数千个分隔符的浮点
    }
    捕获(格式化异常)
    {
    抛出新的格式化异常(
    Format(“输入字符串格式字符串不包含预期的令牌,如”+
    {{runs}/{{0}}、{{time}/{{1}}或{{frequency}/{2}}或格式字符串+
    本身无效:\“{0}\”,格式),ex);
    }
    }
    /// 
    ///执行给定函数n次并打印定时值(运行次数、运行时间、调用频率)
    ///到控制台窗口。
    /// 
    ///函数以在for循环中调用。
    ///迭代次数。
    ///格式字符串,可以包含{runs}或{0}、{time}或{1}和{frequency}或{2}。
    公共静态无效配置文件(此操作func,int运行,字符串格式)
    {
    Func f=()=>
    {
    for(int i=0;iusing System;
    using System.Globalization;
    using System.Diagnostics;
    
    namespace PerformanceTester
    {
       /// <summary>
       /// Helper class to print out performance related data like number of runs, elapsed time and frequency
       /// </summary>
       public static class Extension
       {
           static NumberFormatInfo myNumberFormat;
    
           static NumberFormatInfo NumberFormat
           {
               get
               {
                   if (myNumberFormat == null)
                   {
                       var local = new CultureInfo("en-us", false).NumberFormat;
                       local.NumberGroupSeparator = " "; // set space as thousand separator
                       myNumberFormat = local; // make a thread safe assignment with a fully initialized variable
                   }
                   return myNumberFormat;
               }
           }
    
           /// <summary>
           /// Execute the given function and print the elapsed time to the console.
           /// </summary>
           /// <param name="func">Function that returns the number of iterations.</param>
           /// <param name="format">Format string which can contain {runs} or {0},{time} or {1} and {frequency} or {2}.</param>
           public static void Profile(this Func<int> func, string format)
           {
    
               Stopwatch watch = Stopwatch.StartNew();
               int runs = func();  // Execute function and get number of iterations back
               watch.Stop();
    
               string replacedFormat = format.Replace("{runs}", "{3}")
                                             .Replace("{time}", "{4}")
                                             .Replace("{frequency}", "{5}");
    
               // get elapsed time back
               float sec = watch.ElapsedMilliseconds / 1000.0f;
               float frequency = runs / sec; // calculate frequency of the operation in question
    
               try
               {
                   Console.WriteLine(replacedFormat,
                                       runs,  // {0} is the number of runs
                                       sec,   // {1} is the elapsed time as float
                                       frequency, // {2} is the call frequency as float
                                       runs.ToString("N0", NumberFormat),  // Expanded token {runs} is formatted with thousand separators
                                       sec.ToString("F2", NumberFormat),   // expanded token {time} is formatted as float in seconds with two digits precision
                                       frequency.ToString("N0", NumberFormat)); // expanded token {frequency} is formatted as float with thousands separators
               }
               catch (FormatException ex)
               {
                   throw new FormatException(
                       String.Format("The input string format string did contain not an expected token like "+
                                     "{{runs}}/{{0}}, {{time}}/{{1}} or {{frequency}}/{{2}} or the format string " +
                                     "itself was invalid: \"{0}\"", format), ex);
               }
           }
    
           /// <summary>
           /// Execute the given function n-times and print the timing values (number of runs, elapsed time, call frequency)
           /// to the console window.
           /// </summary>
           /// <param name="func">Function to call in a for loop.</param>
           /// <param name="runs">Number of iterations.</param>
           /// <param name="format">Format string which can contain {runs} or {0},{time} or {1} and {frequency} or {2}.</param>
           public static void Profile(this Action func, int runs, string format)
           {
               Func<int> f = () =>
               {
                   for (int i = 0; i < runs; i++)
                   {
                       func();
                   }
                   return runs;
               };
               f.Profile(format);
           }
    
           /// <summary>
           /// Call a function in a for loop n-times. The first function call will be measured independently to measure
           /// first call effects.
           /// </summary>
           /// <param name="func">Function to call in a loop.</param>
           /// <param name="runs">Number of iterations.</param>
           /// <param name="formatFirst">Format string for first function call performance.</param>
           /// <param name="formatOther">Format string for subsequent function call performance.</param>
           /// <remarks>
           /// The format string can contain {runs} or {0},{time} or {1} and {frequency} or {2}.
           /// </remarks>
           public static void ProfileWithFirst(this Action func, int runs, string formatFirst, string formatOther)
           {
               func.Profile(1, formatFirst);
               func.Profile(runs - 1, formatOther);
           }
       }
    }
    
    using BenchmarkDotNet.Running;
    using BenchmarkDotNet.Attributes;
    class Program
    {
        static void Main()
        {
            var summary = BenchmarkRunner.Run<YourBenchmarks>();
        }
    }
    
    public class YourBenchmarks
    {
        [Benchmark]
        public object HideDataUsingAlgorithm()
        {
            return Namespace.hideDataUsingAlgorithm(); // call the code you want to benchmark here
        }
    }
    
                     Method |      Median |    StdDev |
    ----------------------- |------------ |---------- |
     HideDataUsingAlgorithm | 252.4869 ns | 8.0261 ns |