性能优化之三:将Dottrace过程加入持续集成
之前分享过一篇如何做接口性能分析的文章,但是整个分析过程有点繁琐,需要写一个控制台程序调用被测接口,再预热、启动dottrace追踪,最后才能得到我们想要的性能分析报告。如果有办法一键生成性能分析报告,那就会省很多不必要的时间。这里我们就借助Jenkins自动化完成这一过程。
目标:
把Dottrace的性能分析集成到Jenkins中,使我们在构建的时候,可以触发Dottrace分析指定方法,并生成相关测试报告。
步骤:
-
开发一个业务程序的Host程序,这个程序可以通过反射调用被测的业务方法;
-
在Jenkins中,通过PowerShell调用Dottrace的CommandProfile执行Host程序,Host程序再执行被测业务方法,生成报告。
-
通过邮件把生成的报告发送到我们指定的邮箱
开发Host程序
1. 按照我们公司的规范,每个接口都需要创建UnitTest,用于调试具体某个业务方法。那么,我们被测程序自然就选择这些UnitTest。
2. 做一个PerformanceAnalysisAttribute类,用于标识该方法将被用来执行性能分析。
[AttributeUsage(AttributeTargets.Method)] public class PerformanceAnalysisAttribute:Attribute { public PerformanceAnalysisAttribute() { } /// <summary> /// 暂不支持环境设置,取决于CI环境而定 /// </summary> /// <param name="env"></param> public PerformanceAnalysisAttribute(EnvironmentType env) { Env = env; } public PerformanceAnalysisAttribute(EnvironmentType env,params object[] args) { Args = args; Env = env; } public Object[] Args { get; set; } public EnvironmentType Env { get; set; } } public enum EnvironmentType { Development = 1, Testing = 2 }
3. 开发Host程序,加载符合要求的dll,然后查找带有PerformanceAnalysisAttribute标记的方法,逐个执行
static void Main(string[] args) { var methods = Load(); Console.WriteLine("Config and assemblies loaded"); FirstPreHeat(methods); Console.WriteLine("Finished preheat"); Test(methods); Environment.Exit(0); } static List<MethodInfo> Load() { string dllDir = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase; //1. 加载目录下的*Test.dll //2. 查找*Test.dll中,具备 包含 "PerformanceAnalysis"标签的方法 //3. 逐个执行 var files = Directory.GetFiles(dllDir, "*test.dll"); var assemblies = files.Select(p => Assembly.LoadFile(p)); List<MethodInfo> methodsToRun = new List<MethodInfo>(); foreach(var assembly in assemblies) { foreach(var type in assembly.ExportedTypes) { foreach(var method in type.GetMethods()) { if (method.GetCustomAttributes().Any(att => att.GetType().Name.Contains("PerformanceAnalysis"))) methodsToRun.Add(method); } } } return methodsToRun; } static void FirstPreHeat(List<MethodInfo> methods) { RunTestMethod(methods); } static void Test(List<MethodInfo> methods) { RunTestMethod(methods); } static void RunTestMethod(List<MethodInfo> methods) { foreach(var method in methods) { Object instance = Activator.CreateInstance(method.DeclaringType); method.Invoke(instance, null); Console.WriteLine($"{method.DeclaringType.Name}.{method.Name}执行完毕"); } }
集成到Jenkins
在讲集成之前,我们再回顾一下整个测试、生成报告的过程:
-
在被测方法上,加上 [PerformanceAnalysis] 标签,编译,生成dll
-
把被测业务程序的dll复制到Host程序目录下
-
Host在运行的时候,就会加载Test结尾的dll,并且查找里面[PerformanceAnalysis]标记的方法,然后执行这些方法
-
运行CommandProfiler,trace模式下运行Host程序,就会生成Host以及业务方法的性能分析报告
Jenkins就是通过powershell把这一个过程参数化、自动化。
具体步骤为:
-
在项目中添加一个Powershell步骤
- 写入如下命令:
Invoke-Expression "chcp 65001" write-host $ENV:TestReportPath write-host $ENV:BUILD_TAG $SolutionFile=$ENV:WORKSPACE+"\Solution\MyProject.Dev.sln" $ConFile=$ENV:NuGetConfigFile $TestDlls =$ENV:WORKSPACE+"\Src\MyProject.Test\bin\Debug\*.*" $ClearReportFiles =$ENV:WORKSPACE+"\PerfResult\*.*" $ReportDir =$ENV:WORKSPACE+"\PerfResult\" write-host "SolutionFile " write-host $SolutionFile write-host "ConFile" write-host $ConFile nuget restore -Force $SolutionFile -ConfigFile $ConFile MSBuild $SolutionFile write-host "----------------Build Test Perf---------------------" write-host $TestDlls write-host $ClearReportFiles write-host $ReportDir write-host "-------------MKDIR------------" $CurPerfPath =$ReportDir+$ENV:BUILD_NUMBER write-host $CurPerfPath mkdir $CurPerfPath write-host "-------------COPY------------" copy D:\dottrace\PerformanceAnalysisHost\*.* $CurPerfPath copy $TestDlls $CurPerfPath write-host "-------------ReportDir------------" $CurReportPath =$ENV:WORKSPACE+"\PerformanceReport\"+$ENV:BUILD_NUMBER mkdir $CurReportPath write-host $CurReportPath write-host "-------------ReportVar------------" $ReportFileName =$CurReportPath +"\snapshot.dtp" $PerfToolPath =$CurPerfPath+"\PerformanceAnalysisDemo.exe" write-host $ReportFileName write-host $PerfToolPath write-host "-------------Report------------" D:\dottrace\DotTraceCommandLine\ConsoleProfiler start --save-to=$ReportFileName --overwrite --profiling-type=Tracing $PerfToolPath
- 把报告(或所在路径)
运行结果:
Jenkins测试项目:
分析报告邮件: