标签:
虽然文章题目是针对EF的,但涉及的内容不仅仅是EF。
目前在做的一个项目,行业门户,项目部分站点按域名划分如下:
其中user.xxx.com为个人用户及企业用户登陆入口,
manage.xxx.com/login为网站管理后台登陆入口。
四个项目都是mvc4+ef6+autofac+automapper。
补充信息:
于是,用过ef的都知道,ef首次访问数据库的时候,耗费的时间很长。
如果四个项目都是首次访问,那么个人用户首次登陆的时候,会经历两次ef首次访问(user站和owner站)。
暂不论项目本身是否有更好的架构方案,或者配合集群加一层进行可用性缓冲等。本文的目标就是要尽可能的降低用户在上述情况下遇到的等待时间。
以下所有测试前提:
贴图不太方便,只给搜集的数据作为展示
无任何优化措施的初始状态,更新各站点后:
简单归纳下就是:
1. owner登陆体验到的延迟共计(5.47s + 9.37s + 14.54s) 2. company登陆体验到的延迟共计(15.19s,要感谢登陆owner的时候已经"激活"了user以及user的EF) 3. manage登陆体验到的延迟共计(2.96s + 8.23s)
这时候还没EF什么事,只是一个空的登陆表单
首次访问,一般分两块:
很多.net程序员会忽略这个问题。
(这真的是许多年的无奈经验之谈,大多会说,第一次访问本来就会很慢。)
或者通过脚本定时访问,以规避这个问题(不让用户遇到就行了)
这里我倒想真的试试解决这个问题。
这是在iis8出来后才有的,iis8内置的功能,而对于iis7.5也提供了一个扩展以支持这个功能。
Application Initialization Module for IIS 7.5
在页面接近底部的地方,找到适合自己架构的安装链接
安装这个iis模块后,在iis界面中并没有模块图标和配置界面,还需要安装:
http://files.dotblogs.com.tw/jaigi/1306/2013619347830.zip
具体配置方法见:
如果仅配置程序池StartMode为AlwaysRunning还不放心的话,
也可以同时针对站点开启preload和DoAppInitAfterRestart。
配置好后,测试了下,效果十分不错。
回收程序池后首次打开各站点,延迟都很低。
其实这个模块的思路和定时从外部触发一个访问是一样的,只是,更好的地方在于,它本身在程序池回收重启的时候就完成了这件事,而不会让外部访问有机会遇到首次访问的情况。
好了,完成这一步,解开了多年心结,省了5秒!
这个优化点,一般仔细去EF的网站找找还是容易找到的。
具体原因原理不说了,这里引用下博客园dudu大神的文章。
搬一下代码:
using (var dbcontext = new CnblogsDbContext()) { var objectContext = ((IObjectContextAdapter)dbcontext).ObjectContext; var mappingCollection = (StorageMappingItemCollection)objectContext .MetadataWorkspace.GetItemCollection(DataSpace.CSSpace); mappingCollection.GenerateViews(new List<EdmSchemaError>()); } //对程序中定义的所有DbContext逐一进行这个操作
我把它配置在每个站点的Application_Start中了,我的项目使用了Autofac和Repository+UnitOfWork模式,没有异常。
经过这一环节,又砍掉了剩下延迟中的50%时间,大概4秒多点。
归纳下测试数据:(结合以上两种优化后的成果)
1. owner登陆体验到的延迟共计( <1s + 4.68 + 4.99) 2. company登陆体验到的延迟共计(5.5,同样要感谢登陆owner的时候已经"激活"了user的EF) 3. manage登陆体验到的延迟共计(4.23)
EF的文档要认真看啊!这个真是不小心挖出来的解决方案,主要是被我看到了一句话:
The .NET Framework supports the generation of native images for managed applications and libraries as a way to help applications start faster and also in some cases use less memory.
具体参考:Improving Startup Performance with NGen (EF6 Onwards)
Ngen使用方法:
安装命令:[path to ngen]/ngen.exe install "[path to dll]" 查询命令:[path to ngen]/ngen.exe display System.Xaml /verbose|findstr "EntityFramework" 卸载命令:[path to ngen]/ngen.exe uninstall "[DisplayName in System.Xaml]"
具体原理就不解释了。这里就记一下使用经验:
这一步之后,归纳下测试数据:
1. owner登陆体验到的延迟共计(45ms+1.02s+1.06s) 2. company登陆体验到的延迟共计(1.42s,同样要感谢登陆owner的时候已经"激活"了user的EF) 3. manage登陆体验到的延迟共计(925ms+197ms)
至此,心愿已了~
Ngen这种工具,不知道mono有没有,希望vnext正式版出来后,还能再见。
让IIS 7 如同IIS 8 第一次请求不变慢
Pre-Generated Mapping Views
来,给Entity Framework热热身
Performance Considerations for Entity Framework 4, 5, and 6
Improving Startup Performance with NGen (EF6 Onwards)
标签:
原文地址:http://www.cnblogs.com/lenther2002/p/4814882.html