概要
C# であるメソッドの実行時間・処理時間を測定する処理をよく書くので、備忘録としてメモを残しておきます。
簡易コード
using System.Diagnostics;
public static (TResult result, TimeSpan elapsed) MeasureExecutionTime<TResult>(Func<TResult> method)
{
var stopwatch = Stopwatch.StartNew();
TResult result = method();
stopwatch.Stop();
return (result, stopwatch.Elapsed);
}
試行錯誤してこの形になりました。
コード全文
MethodTimer.cs
// These codes are licensed under CC0. (権利放棄、自由利用可)
//https://creativecommons.org/publicdomain/zero/1.0/deed.ja
using System.Diagnostics;
namespace MethodTimer;
/// <summary>
/// メソッドの実行時間を測定するためのユーティリティクラス
/// </summary>
public static class MethodTimer
{
/// <summary>
/// 戻り値のあるメソッドの実行時間を測定
/// </summary>
/// <typeparam name="TResult">メソッドの戻り値の型</typeparam>
/// <param name="method">実行時間を測定する対象のメソッド</param>
/// <returns>
/// <list type="bullet">
/// <item><description>result: メソッドの実行結果</description></item>
/// <item><description>elapsed: 実行にかかった時間</description></item>
/// </list>
/// </returns>
/// <example>
/// 戻り値のあるメソッドの実行時間を測定する例
/// <code>
/// var (result, elapsed) = MethodTimer.MeasureExecutionTime(() => SomeMethod());
/// Console.WriteLine($"Result: {result}, Elapsed Time: {elapsed.TotalMilliseconds} ms");
/// </code>
/// </example>
public static (TResult result, TimeSpan elapsed) MeasureExecutionTime<TResult>(Func<TResult> method)
{
var stopwatch = Stopwatch.StartNew();
TResult result = method();
stopwatch.Stop();
return (result, stopwatch.Elapsed);
}
/// <summary>
/// 戻り値のないメソッドの実行時間を測定
/// </summary>
/// <param name="method">実行時間を測定する対象のメソッド</param>
/// <returns>実行にかかった時間</returns>
/// <example>
/// 戻り値のないメソッドの実行時間を測定する例
/// <code>
/// var elapsed = MethodTimer.MeasureExecutionTime(() => SomeVoidMethod());
/// Console.WriteLine($"Elapsed Time: {elapsed.TotalMilliseconds} ms");
/// </code>
/// </example>
public static TimeSpan MeasureExecutionTime(Action method)
{
var stopwatch = Stopwatch.StartNew();
method();
stopwatch.Stop();
return stopwatch.Elapsed;
}
/// <summary>
/// 戻り値のあるメソッドの実行時間を測定し、結果をコンソールに出力
/// </summary>
/// <typeparam name="TResult">メソッドの戻り値の型</typeparam>
/// <param name="method">実行時間を測定する対象のメソッド</param>
/// <returns>メソッドの実行結果</returns>
/// <example>
/// 戻り値のあるメソッドの実行時間を測定してログに出力する例
/// <code>
/// var result = MethodTimer.LogExecutionTime(() => SomeMethod());
/// </code>
/// </example>
public static TResult LogExecutionTime<TResult>(Func<TResult> method)
{
var stopwatch = Stopwatch.StartNew();
TResult result = method();
stopwatch.Stop();
Console.WriteLine($"Result: {result}, Elapsed Time: {stopwatch.Elapsed.TotalMilliseconds} ms");
return result;
}
/// <summary>
/// 戻り値のないメソッドの実行時間を測定し、結果をコンソールに出力
/// </summary>
/// <param name="method">実行時間を測定する対象のメソッド</param>
/// <example>
/// 戻り値のないメソッドの実行時間を測定してログに出力する例
/// <code>
/// MethodTimer.LogExecutionTime(() => SomeVoidMethod());
/// </code>
/// </example>
public static void LogExecutionTime(Action method)
{
var stopwatch = Stopwatch.StartNew();
method();
stopwatch.Stop();
Console.WriteLine($"Elapsed Time: {stopwatch.Elapsed.TotalMilliseconds} ms");
}
}
使用例
Program.cs
using static MethodTimer.MethodTimer;
class Program
{
private static void Main()
{
//使用例
var fuga = new FugaClass();
var piyo = new PiyoClass { Value = "Hello" };
// 戻り値あり、引数あり
var (result0, elapsed0) = MeasureExecutionTime(() => fuga.FugaMethod(piyo));
Console.WriteLine($"Result: {result0.Value}, Elapsed Time (result, arg): {elapsed0.TotalMilliseconds} ms");
Console.WriteLine();
// 戻り値なし、引数あり
var elapsed1 = MeasureExecutionTime(() => fuga.FugaMethodVoid(piyo));
Console.WriteLine($"Elapsed Time (void, arg): {elapsed1.TotalMilliseconds} ms");
Console.WriteLine();
// 戻り値あり、引数なし
var (result2, elapsed2) = MeasureExecutionTime(fuga.FugaMethodString);
Console.WriteLine($"Result: {result2}, Elapsed Time (result, no arg): {elapsed2.TotalMilliseconds} ms");
Console.WriteLine();
// 戻り値なし、引数なし
var elapsed3 = MeasureExecutionTime(fuga.FugaMethodVoid);
Console.WriteLine($"Elapsed Time (void, no arg): {elapsed3.TotalMilliseconds} ms");
Console.WriteLine();
//コンソールに実行時間を出力
//戻り値あり、引数あり
HogeClass? result3 = LogExecutionTime(() => fuga.FugaMethod(piyo));
Console.WriteLine($"Result: {result3.Value}");
//戻り値なし、引数あり
LogExecutionTime(() => fuga.FugaMethodVoid(piyo));
Console.WriteLine();
//戻り値あり、引数なし
string? result5 = LogExecutionTime(fuga.FugaMethodString);
Console.WriteLine($"Result: {result5}");
Console.WriteLine();
//戻り値なし、引数なし
LogExecutionTime(fuga.FugaMethodVoid);
Console.WriteLine();
}
}
public class HogeClass
{
public int Value { get; set; }
}
public class FugaClass
{
public HogeClass FugaMethod(PiyoClass arg)
{
Thread.Sleep(400); // ダミー処理
Console.WriteLine($"FugaMethod executed with arg: {arg.Value}");
return new HogeClass() { Value = 0xff };
}
public void FugaMethodVoid(PiyoClass arg)
{
Thread.Sleep(300); // ダミー処理
Console.WriteLine($"FugaMethodVoid executed with arg: {arg.Value}");
}
public string FugaMethodString()
{
Thread.Sleep(200); // ダミー処理
return "Hello, World! by FugaMethodString";
}
public void FugaMethodVoid()
{
Thread.Sleep(100); // ダミー処理
Console.WriteLine("Void method with no arguments executed");
}
}
public class PiyoClass
{
public string Value { get; set; }
}
実行結果
実行結果
FugaMethod executed with arg: Hello
Result: 255, Elapsed Time (result, arg): 428.6967 ms
FugaMethodVoid executed with arg: Hello
Elapsed Time (void, arg): 316.5747 ms
Result: Hello, World! by FugaMethodString, Elapsed Time (result, no arg): 212.1155 ms
Void method with no arguments executed
Elapsed Time (void, no arg): 105.722 ms
FugaMethod executed with arg: Hello
Result: HogeClass, Elapsed Time: 401.6136 ms
Result: 255
FugaMethodVoid executed with arg: Hello
Elapsed Time: 307.6023 ms
Result: Hello, World! by FugaMethodString, Elapsed Time: 214.6779 ms
Result: Hello, World! by FugaMethodString
Void method with no arguments executed
Elapsed Time: 107.0708 ms
使用環境
Visual Studio 2022
.NET 9.0 / C# バージョン 13.0
参考資料
Stopwatch クラス (System.Diagnostics) | Microsoft Learn
ラムダ式 - ラムダ式と匿名関数 - C# reference | Microsoft Learn
Func Delegate (System) | Microsoft Learn
デリゲート - C# によるプログラミング入門 | ++C++; // 未確認飛行 C