一次WinForm性能优化
起因
项目中在加载控件,出现闪烁/慢的情况,针对这些问题做出处理,主要是以下两点.
优化自定义控件加载
调整前:
一个大模板有若干小模板,小模板是自定义控件,在小模板上有Label、TextBox等一些控件,在项目加载大模板的时候,因为控件比较多,出现闪烁现象。每次获取新数据的时候,先把小模板移除,再重新创建小模板,然后添加到容器中。
从创建小模版到加载完成,耗时在5s左右,刚开始凭直觉,以为是反射创建小模版,将反射创建改为创建委托.反射耗时1.5s左右,使用委托减少700ms,发现最耗时的操作不是反射.而是将控件添加到窗体上.
//创建委托
private static T GenerateNewObjDelegate<T>(Type type) where T : class
{
// Create a new, parameterless (specified by Type.EmptyTypes) dynamic method.
var dynamicMethod = new DynamicMethod("Ctor_" + type.FullName, type, Type.EmptyTypes, true);
var ilGenerator = dynamicMethod.GetILGenerator();
// Look up the constructor info for the type we want to create
var ctorInfo = type.GetConstructor(Type.EmptyTypes);
if (ctorInfo != null)
{
ilGenerator.Emit(OpCodes.Newobj, ctorInfo);
ilGenerator.Emit(OpCodes.Ret);
object del = dynamicMethod.CreateDelegate(typeof(T));
return (T)del;
}
return null;
}
使用Profiler工具
使用ants-performance-profile监测项目,发现耗时操作是将小模版添加到窗体中,造成winform界面一直在绘制.
关于.Net Profiler好用的工具:
Redgate家: ANTS Performance Profiler和ANTS Memory Profiler
Jetbrains家: dotTrace和dotMemory
调整后:
在不切换大模板的时候,只是把小模板的数据清空。这样避免了每次创建控件、添加到容器中,然后移除控件。
优化接口服务调用
1. 发现个别模块,在每一次获取数据的时候,有重复调用的情况,移除重复调用的函数。2. 找出耗时的接口服务,优化Sql查询,比如说常见的缺少索引
总结
- 减少控件创建(减少对象创建,就是减少GC回收的次数)
- 减少界面绘制(这里是本次最耗时的操作)
- 优化接口返回数据的速度
秋风
2019-06-02