大家来看看这道面试题,性能优化
请罗列几条你认为大型网站性能调优中比较重要的方法。比如:猫扑、Sina、网易、微软他们的网站是如何做到性能调优的。又比如:曾经有个牛人,把全美国电话号码查询程序平均查询时间从40多秒优化到5秒,你认为他是如何优化的呢?
[解决办法]
6. 只要可能,就缓存数据和页输出
ASP.NET 提供了一些简单的机制,它们会在不需要为每个页请求动态计算页输出或数据时缓存这些页输出或数据。另外,通过设计要进行缓存的页和数据请求(特别是在站点中预期将有较大通讯量的区域),可以优化这些页的性能。与 .NET Framework 的任何 Web 窗体功能相比,适当地使用缓存可以更好的提高站点的性能,有时这种提高是超数量级的。
使用 ASP.NET 缓存机制有两点需要注意。首先,不要缓存太多项。缓存每个项均有开销,特别是在内存使用方面。不要缓存容易重新计算和很少使用的项。其次,给缓存的项分配的有效期不要太短。很快到期的项会导致缓存中不必要的周转,并且经常导致更多的代码清除和垃圾回收工作。若关心此问题,请监视与 ASP.NET Applications 性能对象关联的 Cache Total Turnover Rate 性能计数器。高周转率可能说明存在问题,特别是当项在到期前被移除时。这也称作内存压力。
7. 选择适合页面或应用程序的数据查看机制
根据您选择在 Web 窗体页显示数据的方式,在便利和性能之间常常存在着重要的权衡。例如,DataGrid Web 服务器控件可能是一种显示数据的方便快捷的方法,但就性能而言它的开销常常是最大的。在某些简单的情况下,您通过生成适当的 HTML 自己呈现数据可能很有效,但是自定义和浏览器定向会很快抵销所获得的额外功效。Repeater Web 服务器控件是便利和性能的折衷。它高效、可自定义且可编程。
8. 将 SqlDataReader 类用于快速只进数据游标
SqlDataReader 类提供了一种读取从 SQL Server 数据库检索的只进数据流的方法。如果当创建 ASP.NET 应用程序时出现允许您使用它的情况,则 SqlDataReader 类提供比 DataSet 类更高的性能。情况之所以这样,是因为 SqlDataReader 使用 SQL Server 的本机网络数据传输格式从数据库连接直接读取数据。另外,SqlDataReader 类实现 IEnumerable 接口,该接口也允许您将数据绑定到服务器控件。有关更多信息,请参见 SqlDataReader 类。有关 ASP.NET 如何访问数据的信息,请参见通过 ASP.NET 访问数据。
9. 将 SQL Server 存储过程用于数据访问
在 .NET Framework 提供的所有数据访问方法中,基于 SQL Server 的数据访问是生成高性能、可缩放 Web 应用程序的推荐选择。使用托管 SQL Server 提供程序时,可通过使用编译的存储过程而不是特殊查询获得额外的性能提高。
10. 避免单线程单元 (STA) COM 组件
默认情况下,ASP.NET 不允许任何 STA COM 组件在页面内运行。若要运行它们,必须在 .aspx 文件内将 ASPCompat=true 属性包含在 @ Page 指令中。这样就将执行用的线程池切换到 STA 线程池,而且使 HttpContext 和其他内置对象可用于 COM 对象。前者也是一种性能优化,因为它避免了将多线程单元 (MTA) 封送到 STA 线程的任何调用。
使用 STA COM 组件可能大大损害性能,应尽量避免。若必须使用 STA COM 组件,如在任何 interop 方案中,则应在执行期间进行大量调用并在每次调用期间发送尽可能多的信息。另外,小心不要在构造页面期间创建任何 STA COM 组件。例如下面的代码中,在页面构造时将实例化由某个线程创建的 MySTAComponent,而该线程并不是将运行页面的 STA 线程。这可能对性能有不利影响,因为要构造页面就必须完成 MTA 和 STA 线程之间的封送处理。
<%@ Page Language="VB" ASPCompat="true" %>
<script runat=server>
Dim myComp as new MySTAComponent()
Public Sub Page_Load()
myComp.Name = "Bob"
End Sub
</script>
<html>
<%
Response.Write(myComp.SayHello)
%>
</html>
首选机制是推迟对象的创建,直到以后在 STA 线程下执行上述代码,如下面的例子所示。
<%@ Page Language="VB" ASPCompat="true" %>
<script runat=server>
Dim myComp
Public Sub Page_Load()
myComp = new MySTAComponent()
myComp.Name = "Bob"
End Sub
</script>
<html>
<%
Response.Write(myComp.SayHello)
%>
</html>
推荐的做法是在需要时或者在 Page_Load 方法中构造任何 COM 组件和外部资源。
永远不要将任何 STA COM 组件存储在可以由构造它的线程以外的其他线程访问的共享资源里。这类资源包括像缓存和会话状态这样的资源。即使 STA 线程调用 STA COM 组件,也只有构造此 STA COM 组件的线程能够实际为该调用服务,而这要求封送处理对创建者线程的调用。此封送处理可能产生重大的性能损失和可伸缩性问题。在这种情况下,请研究一下使 COM 组件成为 MTA COM 组件的可能性,或者更好的办法是迁移代码以使对象成为托管对象。
11. 将调用密集型的 COM 组件迁移到托管代码
.NET Framework 提供了一个简单的方法与传统的 COM 组件进行交互。其优点是可以在保留现有投资的同时利用新的平台。但是在某些情况下,保留旧组件的性能开销使得将组件迁移到托管代码是值得的。每一情况都是不一样的,决定是否需要迁移组件的最好方法是对 Web 站点运行性能测量。建议您研究一下如何将需要大量调用以进行交互的任何 COM 组件迁移到托管代码。
许多情况下不可能将旧式组件迁移到托管代码,特别是在最初迁移 Web 应用程序时。在这种情况下,最大的性能障碍之一是将数据从非托管环境封送到托管环境。因此,在交互操作中,请在任何一端执行尽可能多的任务,然后进行一个大调用而不是一系列小调用。例如,公共语言运行库中的所有字符串都是 Unicode 的,所以应在调用托管代码之前将组件中的所有字符串转换成 Unicode 格式。
另外,一处理完任何 COM 对象或本机资源就释放它们。这样,其他请求就能够使用它们,并且最大限度地减少了因稍后请求垃圾回收器释放它们所引起的性能问题。