a亚洲精品_精品国产91乱码一区二区三区_亚洲精品在线免费观看视频_欧美日韩亚洲国产综合_久久久久久久久久久成人_在线区

首頁 > 編程 > C# > 正文

如何獲取C#中方法的執行時間以及其代碼注入詳解

2019-10-29 19:57:59
字體:
來源:轉載
供稿:網友

前言

在優化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代碼:

C#,執行時間,代碼注入

代碼注入后IL代碼:

C#,執行時間,代碼注入

代碼注入后運行結果:

 C#,執行時間,代碼注入

 總結:

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 中文字幕在线电影观看 | 日韩欧美一二三区 | 欧美精品在线免费观看 | 亚洲三级免费观看 | 国产成人在线免费观看视频 | 欧美天堂在线观看 | 国产日韩在线视频 | 国产精品毛片在线看 | 凹凸日日摸日日碰夜夜 | 天堂网av2020| 成人作爱视频 | 亚洲精品久久久一区二区三区 | 一级久久久| 欧美激情视频免费观看 | 黄色av电影在线看 | 欧美日韩国产在线观看 | 久久这里精品 | 一级片手机免费看 | 91精品国产91久久久久久久久久久久 | 色欧美片视频在线观看 | 欧美视频免费在线 | 免费av在线网站 | 久久影院一区 | 黄页网站在线免费观看 | 999在线观看精品免费不卡网站 | 成年人网站免费在线观看 | 国产成人免费在线视频 | 91福利在线播放 | 国产乱码精品一区二区三区av | 青草av在线 | 性色av网 | 精品一区二区在线播放 | 欧美一区二区三区视频 | 欧美1级 | 午夜视频在线观看网站 | 欧美精品片| 欧美成人一区二区三区片免费 | 北条麻妃99精品青青久久 | 国产精品毛片一区二区 | 欧美日韩视频在线 | 久久国产乱子伦精品免费午夜,浪货好紧 |