日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > C# >内容正文

C#

获取C#中方法的执行时间及其代码注入

發布時間:2025/4/16 C# 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 获取C#中方法的执行时间及其代码注入 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

  在優化C#代碼或對比某些API的效率時,通常需要測試某個方法的運行時間,可以通過DateTime來統計指定方法的執行時間,也可以使用命名空間System.Diagnostics中封裝了高精度計時器QueryPerformanceCounter方法的Stopwatch類來統計指定方法的執行時間:

  1.使用DateTime方法:

DateTime dateTime = DateTime.Now;
MyFunc();
Console.WriteLine((DateTime.Now
- dateTime).TotalMilliseconds);

  2.使用Stopwatch方式:

Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); MyFunc();
stopwatch.Stop();
Console.WriteLine(stopwatch.ElapsedMilliseconds);
//本次MyFunc()方法的運行毫秒數
//重置計時器 stopwatch.Restart(); //此處可以使用stopwatch.Reset(); stopwatch.Start();組合代替
MyFunc();
stopwatch.Stop(); Console.WriteLine(stopwatch.ElapsedMilliseconds);
//本次MyFunc()方法的運行毫秒數

?

  以上兩種辦法都可以達到獲取方法執行時間的目的,但是在需要對整個項目中的方法都進行監測用時時,除了使用性能分析工具,我們還可以通過代碼注入的方式給程序集中每一個方法加入計時器;

  通過命名空間System.Reflection.Emit中的類可以動態的創建程序集、類型和成員,通常類庫Mono.Cecil可以動態讀取并修改已經生成的IL文件,這種在不修改源代碼的情況下給程序集動態添加功能的技術稱為面向切面編程(AOP);

  這里給出了一個注入使用Stopwatch來檢測方法執行時間的代碼,這里的Mono.Cecil類庫可以通過nuget進行安裝:

?

using System; using System.IO; using System.Linq; using System.Diagnostics; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic;

?

static void Main(string[] args){for (int i = 0; i < args.Length; i++){FileStream fileStream = new FileStream(args[i], FileMode.Open);if (fileStream != null){AssemblyDefinition aD = AssemblyDefinition.ReadAssembly(fileStream);ModuleDefinition mD = aD.MainModule;Collection<TypeDefinition> typeDefinition = mD.Types;foreach (TypeDefinition type in typeDefinition){if (type.IsClass){foreach (MethodDefinition method in type.Methods){if (method.IsPublic && !method.IsConstructor){ILProcessor il = method.Body.GetILProcessor();TypeReference stT = mD.ImportReference(typeof(Stopwatch));VariableDefinition stV = new VariableDefinition(stT);method.Body.Variables.Add(stV);Instruction first = method.Body.Instructions.First();il.InsertBefore(first, il.Create(OpCodes.Newobj,
                      mD.ImportReference(
typeof(Stopwatch).GetConstructor(new Type[] { }))));il.InsertBefore(first, il.Create(OpCodes.Stloc_S, stV));il.InsertBefore(first, il.Create(OpCodes.Ldloc_S, stV));il.InsertBefore(first, il.Create(OpCodes.Callvirt,
                      mD.ImportReference(
typeof(Stopwatch).GetMethod("Start"))));Instruction @return = method.Body.Instructions.Last();il.InsertBefore(@return, il.Create(OpCodes.Ldloc_S, stV));il.InsertBefore(@return, il.Create(OpCodes.Callvirt,
                      mD.ImportReference(
typeof(Stopwatch).GetMethod("Stop"))));il.InsertBefore(@return, il.Create(OpCodes.Ldstr, $"{method.FullName} run time: "));il.InsertBefore(@return, il.Create(OpCodes.Ldloc_S, stV));il.InsertBefore(@return, il.Create(OpCodes.Callvirt,
                      mD.ImportReference(
typeof(Stopwatch).GetMethod("get_ElapsedMilliseconds"))));il.InsertBefore(@return, il.Create(OpCodes.Box, mD.ImportReference(typeof(long))));il.InsertBefore(@return, il.Create(OpCodes.Call,
                      mD.ImportReference(
typeof(string).GetMethod("Concat", new Type[] { typeof(object), typeof(object) }))));il.InsertBefore(@return, il.Create(OpCodes.Call,
                      mD.ImportReference(
typeof(Console).GetMethod("WriteLine", new Type[] { typeof(string) }))));}}}}FileInfo fileInfo = new FileInfo(args[i]);string fileName = fileInfo.Name;int pointIndex = fileName.LastIndexOf('.');string frontName = fileName.Substring(0, pointIndex);string backName = fileName.Substring(pointIndex, fileName.Length - pointIndex);string writeFilePath = Path.Combine(fileInfo.Directory.FullName, frontName + "_inject" + backName);aD.Write(writeFilePath);Console.WriteLine($"Success! Output path: {writeFilePath}");fileStream.Dispose();}}Console.Read();}

?

  完整的項目傳到了Github上=>InjectionStopwatchCode,下載項目后,通過dotnet build命令即可編譯出可執行程序,將目標程序集文件拖入到該應用程序即可在程序集目錄導出注入代碼后的程序集文件,經過測試,包括方法擁有返回值和方法的參數列表中包含out和ref參數等情況都不會對運行結果產生影響;

  示例:

using System;public class MyClass {public void MyFunc(){int num = 1;for (int i = 0; i < int.MaxValue; i++){num++;}} } public class Program {public static void Main(string[] args){MyClass myObj = new MyClass();myObj.MyFunc();Console.Read();} }

  原始IL代碼:

  代碼注入后IL代碼:

  代碼注入后運行結果:

?

?


?如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的認可是我寫作的最大動力!

作者:Minotauros
出處:https://www.cnblogs.com/minotauros/

本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接,否則保留追究法律責任的權利。

轉載于:https://www.cnblogs.com/minotauros/p/9930163.html

《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的获取C#中方法的执行时间及其代码注入的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。