小編給大家分享一下怎么獲取C#中方法的執(zhí)行時(shí)間以及其代碼注入,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!
前言
在優(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代碼:
代碼注入后IL代碼:
代碼注入后運(yùn)行結(jié)果:
看完了這篇文章,相信你對(duì)“怎么獲取C#中方法的執(zhí)行時(shí)間以及其代碼注入”有了一定的了解,如果想了解更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計(jì)公司行業(yè)資訊頻道,感謝各位的閱讀!
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。
名稱欄目:怎么獲取C#中方法的執(zhí)行時(shí)間以及其代碼注入-創(chuàng)新互聯(lián)
URL地址:http://www.rwnh.cn/article6/doshog.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供域名注冊(cè)、微信公眾號(hào)、外貿(mào)建站、用戶體驗(yàn)、網(wǎng)站營(yíng)銷、電子商務(wù)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容