第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定

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

標(biāo)簽:
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代码:

  代码注入后运行结果:


點(diǎn)擊查看更多內(nèi)容
TA 點(diǎn)贊

若覺得本文不錯(cuò),就分享一下吧!

評(píng)論

作者其他優(yōu)質(zhì)文章

正在加載中
  • 推薦
  • 評(píng)論
  • 收藏
  • 共同學(xué)習(xí),寫下你的評(píng)論
感謝您的支持,我會(huì)繼續(xù)努力的~
掃碼打賞,你說(shuō)多少就多少
贊賞金額會(huì)直接到老師賬戶
支付方式
打開微信掃一掃,即可進(jìn)行掃碼打賞哦
今天注冊(cè)有機(jī)會(huì)得

100積分直接送

付費(fèi)專欄免費(fèi)學(xué)

大額優(yōu)惠券免費(fèi)領(lǐng)

立即參與 放棄機(jī)會(huì)
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)

舉報(bào)

0/150
提交
取消