麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁(yè) > 編程 > C# > 正文

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

2019-10-29 19:57:59
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

前言

在優(yōu)化C#代碼或?qū)Ρ饶承〢PI的效率時(shí),通常需要測(cè)試某個(gè)方法的運(yùn)行時(shí)間,可以通過(guò)DateTime來(lái)統(tǒng)計(jì)指定方法的執(zhí)行時(shí)間,也可以使用命名空間System.Diagnostics中封裝了高精度計(jì)時(shí)器QueryPerformanceCounter方法的Stopwatch類來(lái)統(tǒng)計(jì)指定方法的執(zhí)行時(shí)間:

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()方法的運(yùn)行毫秒數(shù)//重置計(jì)時(shí)器stopwatch.Restart(); //此處可以使用stopwatch.Reset(); stopwatch.Start();組合代替MyFunc();stopwatch.Stop();Console.WriteLine(stopwatch.ElapsedMilliseconds); //本次MyFunc()方法的運(yùn)行毫秒數(shù)

以上兩種辦法都可以達(dá)到獲取方法執(zhí)行時(shí)間的目的,但是在需要對(duì)整個(gè)項(xiàng)目中的方法都進(jìn)行監(jiān)測(cè)用時(shí)時(shí),除了使用性能分析工具,我們還可以通過(guò)代碼注入的方式給程序集中每一個(gè)方法加入計(jì)時(shí)器;

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

這里給出了一個(gè)注入使用Stopwatch來(lái)檢測(cè)方法執(zhí)行時(shí)間的代碼,這里的Mono.Cecil類庫(kù)可以通過(guò)nuget進(jìn)行安裝:

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(); }

完整的項(xiàng)目傳到了Github上=>InjectionStopwatchCode,下載項(xiàng)目后,通過(guò)dotnet build命令即可編譯出可執(zhí)行程序,將目標(biāo)程序集文件拖入到該應(yīng)用程序即可在程序集目錄導(dǎo)出注入代碼后的程序集文件,經(jīng)過(guò)測(cè)試,包括方法擁有返回值和方法的參數(shù)列表中包含out和ref參數(shù)等情況都不會(huì)對(duì)運(yùn)行結(jié)果產(chǎn)生影響;

示例:

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#,執(zhí)行時(shí)間,代碼注入

代碼注入后IL代碼:

C#,執(zhí)行時(shí)間,代碼注入

代碼注入后運(yùn)行結(jié)果:

 C#,執(zhí)行時(shí)間,代碼注入

 總結(jié):

以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)VEVB武林網(wǎng)的支持。


注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到c#教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 亚洲网站在线播放 | 久久精品一区二区三区国产主播 | 欧美激情区 | 婷婷久久网 | 久久九九热re6这里有精品 | 国内久久久久 | 成人在线观看免费爱爱 | 一级毛片电影网 | 91羞羞 | 思思久而久而蕉人 | 亚洲第一成人久久网站 | 亚洲精品aa | 特一级黄色毛片 | 欧美一级黄色片免费观看 | 中文字幕一二区 | 夜间福利网站 | www.com超碰 | 国产手机av在线 | 欧日韩 | 久久久久9999| 成人福利在线免费观看 | 99国产精成人午夜视频一区二区 | 91麻豆精品国产91久久久无需广告 | 曰韩av在线 | 亚洲电影免费观看国语版 | 久久免费视频一区二区三区 | 中国国语毛片免费观看视频 | 一级毛片免费高清 | 亚洲福利视频52 | 狠狠撸电影 | 国产精品免费观看视频 | 在线看免电影网站 | 性视频久久 | 日韩av在线影院 | 免费国产网站 | 在线a毛片免费视频观看 | 91久久国产露脸精品国产护士 | 亚洲第一精品在线 | av电影在线播放 | 高清视频91 | 日本特级a一片免费观看 |