재우니의 블로그




Haroon Waheed



SQL Server & .NET Devotee

 

 

최상의 coding policies & practices  을 적용해도 우리는 asp.net 어플리케이션으로 부터 바라는 만큼 성능을 얻지 못하고 있습니다. 왜냐면 ASP.NET 어플리케이션에 직접적으로 영향을 주는 또다른 매우 중요한 많은 이유가 있기 때문입니다.

시스템 이외에 좋은 성능을 얻기 위해서는 상세한 아키텍쳐, 디자인, 코딩 그리고 배포가 요구되는데요.

이번 내용은 ASP.NET 성능을 최대화를 위해 구현할 수 있는 다소 많은 성능을 미조정(微調整)하기 위한 리스트를

보여줄 것입니다.

 

 

불필요한 HTTP Modules 를 제거해라


There are various HTTP modules in ASP.NET that intercept each request sent to the server. Session State is a very commonly used HTTP module used to load session data in context object. It’s referred with SessionStateModule name. HTTP modules kick in at each request and process them, therefore if you are not using the functionality provided by the module there is no use referring it as they would use additional CPU cycles. There is a list of HTTP Modules that your application automatically uses when it inherits config setting from web.config placed in $WindowsFolder\Microsoft.NET\Framework\$versiosn\CONFIG folder.
Below is a list of such entries:

 

<httpModules>
  <add name="OutputCache" type="System.Web.Caching.OutputCacheModule"/>
  <add name="Session" type="System.Web.SessionState.SessionStateModule"/>
  <add name="WindowsAuthentication" type="System.Web.Security.WindowsAuthenticationModule"/>
  <add name="FormsAuthentication" type="System.Web.Security.FormsAuthenticationModule"/>
  <add name="PassportAuthentication" type="System.Web.Security.PassportAuthenticationModule"/>
  <add name="RoleManager" type="System.Web.Security.RoleManagerModule"/>
  <add name="UrlAuthorization" type="System.Web.Security.UrlAuthorizationModule"/>
  <add name="FileAuthorization" type="System.Web.Security.FileAuthorizationModule"/>
  <add name="AnonymousIdentification" type="System.Web.Security.AnonymousIdentificationModule"/>
  <add name="Profile" type="System.Web.Profile.ProfileModule"/>
  <add name="ErrorHandlerModule" type="System.Web.Mobile.ErrorHandlerModule, System.Web.Mobile, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
  <add name="ServiceModel" type="System.ServiceModel.Activation.HttpModule, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
</httpModules> 


 

There are bunch of HTTP modules listed here and I am quite positive not all of them are being used by your application. Removing unused HTTP module can definitely give slight performance boost as there would be less work to be performed. Suppose one doesn’t needs Windows authentication in application. To remove the inherited setting, under httpModules section in your web.config application add a remove element and specify name of the module that isn’t required.

  

Example: 


      <httpModules>
            <remove name="WindowsAuthentication" />
      </httpModules>

<compilation debug=”true”/> Killer





As a developer I have seen numerous incidents were the application is deployed to production with <compilation debug=”true”/>. This is really a performance killer because:

  • Compilation of ASP.NET pages take longer.
  • Code execute slower as debug paths are enabled.
  • More memory is used by the application.
  • Scripts and images from WebResource.axd handler are not cached.



Always make sure that debug flag is set to false on production instances. You can override this by specifying following entry in machine.config for production instances:


      <configuration>
            <system.web>
                    <deployment retail=true/>
            </system.web>
      </configuration>


This will disable the <compilation debug=”true”/> for all applications deployed on the server.



Tracing 꺼라

Do remember to turn off tracing before deploying application to production. Tracing adds additional overload to your application which is not required in production environment. To disable tracing use the following entries:


      <configuration>
            <system.web>
                    <trace enabled="false" />
            </system.web>
      </configuration>



 

프로세스 모델을 최적화 해라

ASP.NET allows you to define many process level properties. You can get the detail of all these properties from http://msdn.microsoft.com/en-us/library/7w2sway1.aspx.  By default these are set to auto config. This means that ASP.NET automatically configures maxWorkerThreads, maxIoThreads, minFreeThreads, minLocalRequestFreeThreads and maxConnection to achieve optimal performance. You can tailor these by specifying your own value to achieve better performance. Some of the major settings are:


  • maxWorkerThreads. The default value is 20 per process and it determines the maximum number for request that ASP.NET can process in a given second. For application that are not CPU intensive and most of time wait on database request or any external processing this can increased to get better performance.

  • maxIOThreads. The default value is 20 per process and it determines the maximum number for I/O request that ASP.NET can process in a given second. If you have enough I/O resources you can increase this value for better results.

  • memoryLimit: The default is 60%. This is the max memory ASP.NET can use until worker process is refreshed. If you have a dedicated web server with no other services running you can increase this value for better results. 

  • connectionManagement: This is a property of System.Net configuration and specifies the maximum parallel connections that can be established to a server. If your web application extensively connects to other server you can increase this value.


  • Buffering 활성화 해라

    Make sure that buffering is enabled unless you have a specific need to turn it off. By default its enabled. ASP.Net sends response to IIS in a 31 KB buffer which then passes that to the client. When buffering is disabled ASP.NET only sends few characters to IIS thus not utilizing this buffer and increasing the trips between IIS and the worker process. To enable it you can change the web.config or enable it on each page through @page directive


        <pages buffer="true">

          <%@ Page Buffer="true"%>


      





    Caching 을 사용해라

    Caching in ASP.NET dramatically help in boosting application performance by reducing the load on the underlying server and serving cached content that doesn’t need to be recreated on each request. ASP.NET provides two types of caching:

    • Output Cache which stores dynamic pages and user controls. One each request code is not executed if a cached version of page or control is available 
    • Data Cache which allows application to save application objects, DataSet etc in server memory so they are not recreated on each request.

    Use caching whenever possible to reduce the load on your web server and to increase response time.


    Caching is a huge topic can not be discussed in detail in one post. For more details visit http://msdn.microsoft.com/en-us/library/xsbfdd8c.aspx.




    Kernel Cache 사용해라

    Use Kernel Cache if you are using IIS 6 or above. When Output cache is used in ASP.NET the request still goes to ASP.NET that itself returns the cached content. However if Kernel Cache is enabled and the request is output cached by ASP.NET, IIS receives the cached content. If a request comes for that data again IIS will serve the cached content and end the response. This can save valuable CPU cycles as it minimizes work performed by ASP.NET.


     


    Response.Redirect 의 사용을 피해라

    Instead of using Response.Redirect, use Server.Transfer where ever you can. Response.Redirect sends response to the client which then sends a new request to the server. Server.Transfer however performs the redirect on the server. Only use Response.Redirect when you want authentication and authorization to be performed on redirects or you want URL on client browser to be changed because Server.Transfer will not do this as it is a server side transfer.




    서버측에서 Validation 의 사용을 피해라

    Where ever you can use client-side validation instead of Server-Side validation. This will save you from additional reposts in cases in invalid input. If you don’t trust the browsers that they will be able to perform complex validations still use client-side validation and on repost check Page.IsValid to check if the input passed the given set of rules.




    DataBinder.Eval 호출을 피해라

    Avoid calling DataBinder.Eval multiple times for example in case of grids, repeaters etc. Instead use Continer.DataBind. DataBinder.Eval uses reflection to eval!uate the arguments and therefore can decrease performance if called numerous times.




    Page.DataBind 사용을 피해라

    Never call Page.DataBind until your really need to do so. Instead if you want to bind a specific control only bind that. Calling Page.DataBind will call DataBind for all the controls that support binding.





    ViewState 최적화 해라

    Avoid using ViewState for storing huge objects or disable it when you don’t need it. ViewState is also used by server controls so that they can retain their state after postback. You can also save your objects that are marked Serializable in the ViewState. ASP.NET serializes all objects and controls in the ViewState and transmits them in a hidden field to the browser. If not managed properly ViewState can increase page size and therefore increase network traffic. Also precious CPU cycles are used for Serialization and De-Serialization of ViewState objects. Disable ViewState if:

    • Your pages don’t do postback.
    • You controls are not bound to a data source or they don’t handle server events like 0nClick, 0nSelectedIndexChanged etc or their properties are set on each postback
    • You recreate controls on every postback.

    You can disable ViewState in both web.config or @Page directive


     

          <pages enableViewState="false">
          or
          <%@ Page EnableViewState="false"%> 


     


    ViewState 압축 또는 저장해라

    In case where ViewState in mandatory and the ViewState contains enough data that can cause Network congestion or increase download response time for the user try saving or compressing the ViewState. The Page class provide two very useful methods LoadPageStateFromPersistenceMedium() and SavePageStateToPersistenceMedium(object ViewState). You can override these methods to either compress the ViewState or even prevent it from going to the client by saving it in some persistent medium on the server.


    HTTP Compression 을 사용해라

    If your page size is large enough to cause noticeable lag between subsequent request and response you can use HTTP compression. HTTP compression is a feature of IIS and what it means is that you can compress data sent to the client using compression techniques like GZIP and Deflate. On the other side the browser decompresses the data and shows the response to the client. Most of the modern browser are capable of handling compressed data. You will certainly get a huge performance boost if your page size is large.

    For more details on HTTP compression visit







    데이타 페이징 / 정렬을 쿼리로 커스텀화 해라

    When ever using data grid to show data with paging enabled one thing needs to understood that if your query returned let say 5000 record and you are only showing 100 records per page the rest of the 4900 record will be discarding and the same will apply when ever you will change the page or apply sorting. The additional 4900 rows will definitely take up memory and if your database is located on a different server which is most commonly the case you will also be transferring unnecessary data over the network. Make sure you are only returning the required results to the ASP.NET application by filtering out the data in your database query and apply custom paging. SQL Server 2005 and onwards provide valuable function for ranking data that can be used to accomplish this.




    Connection Pooling

    Creating a connection to a database is a resource intensive process and takes time. Connection pooling allows you to reuse these connections saving time and resources. When a new connection is requested the connection pool managers first searches in the connection pool and if doesn’t finds one, it creates a new one. There are various things that need to be done to use connection pooling effectively:

    • Avoid Connection Leakage. This means that you opened a connection but didn’t close it. If you don’t close the connection the connection pool manager will never put it in the pool for later reuse until the GC is called.
    • Use the same connection string. Connection pool manager searches for similar connection in the pool by the connection string.
    • Use SQL Servers and .NET CLR Data performance counters to monitor pooling.
    • Open connections as late as possible and close them as early as possible
    • Don’t share same connection between multiple function calls. Instead open a new connection and close it in each function.
    • Close transactions prior to closing the connection.
    • Keep at least one connection open to maintain the connection pool.

     

    한꺼번에 Database 을 접근하는것을 피해라

    Avoid accessing database multiple times for the same request. Analyze your code and see if you can reduce the number of trips to database because these trips reduce the number of request per second your application can serve. You can do this by returning multiple records in the same stored proc, combining multiple DB operations in same stored proc etc.


     


    DataSet 대신에 DataReader  을 사용해라

    Use DataReader objects instead of DataSet when ever you need to display data. DataReader is the most efficient means of data retrieval! as they are read and forward only. DataSet are disconnected and in-memory therefore uses valuable server resources. Only use them when you need the same data more then once or want to do some processing on the data.

    Last but certainly not the least follow the best coding, design and deployment patterns and practices. Here are few more usefull links that can be very helpful in performance optimization of you ASP.NET application