ASP.NETがトップページのパフォーマンスを向上させる十大方法

13584 ワード

前言
本文は私がASPに対してNETページの読み込み速度が向上するいくつかの方法は、次のセクションに分けられます.
1.HTTP Moduleを使用してページのライフサイクルを制御します.
2.カスタムResponse.Filterは、出力ストリームstreamが動的ページの静的コンテンツ(ディスクキャッシュ)を生成することを得る.
3.ページGZIP圧縮.
4.OutputCacheプログラミング方式出力ページキャッシュ.
5.ページの空白文字列を削除します.(Googleのような)
6.View Stateを完全に削除します.
7.サーバーコントロールによって生成されたゴミNamingContainerを削除します.
8.計画タスクを使用して、時間通りにページを生成します.(本明細書には、このアプローチの実装は含まれていません)
9.JS、CSS圧縮、マージ、キャッシュ、ピクチャキャッシュ.(文章の紙面に限られ、本文にはそのやり方の実現は含まれていない)
10.キャッシュ破壊.(第9のアプローチの実装は含まれていません)
上記の方法では、まず、ページプロセス全体のエントリとコアであるHTTPモジュールが必要です.
一、カスタムResponse.Filterは出力ストリームstreamを得て動的ページの静的コンテンツ(ディスクキャッシュ)を生成する
次のコードから分かるようにrequest.RawUrlはキャッシュベースである、任意のQueryString変数を含むことができるため、MD 5でRawUrlを暗号化してサーバのローカルファイル名の変数を取得し、FileInfoをインスタンス化してファイルを操作し、ファイルの最終生成時間が7日未満であれば使用する.Net2.0新しいTransmitFileメソッドは、ファイルの静的コンテンツをブラウザに送信します.ファイルが存在しない場合はresponseを操作します.Filterで得られたStreamはCommonFilterクラスに渡され,FileStreamを利用して動的ページの内容を静的ファイルに書き込む.
 
  
namespace ASPNET_CL.Code.HttpModules {
public class CommonModule : IHttpModule {
public void Init( HttpApplication application ) {
application.BeginRequest += Application_BeginRequest;
}
private void Application_BeginRequest( object sender, EventArgs e ) {
var context = HttpContext.Current;
var request = context.Request;
var url = request.RawUrl;
var response = context.Response;
var path = GetPath( url );
var file = new FileInfo( path );
if ( DateTime.Now.Subtract( file.LastWriteTime ).TotalDays < 7 ) {
response.TransmitFile( path );
response.End();
return;
}
try {
var stream = file.OpenWrite();
response.Filter = new CommonFilter( response.Filter, stream );
}
catch ( Exception ) {
//Log.Insert("");
}
}
public void Dispose() {
}
private static string GetPath( string url ) {
var hash = Hash( url );
string fold = HttpContext.Current.Server.MapPath( "~/Temp/" );
return string.Concat( fold, hash );
}
private static string Hash( string url ) {
url = url.ToUpperInvariant();
var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
var bs = md5.ComputeHash( Encoding.ASCII.GetBytes( url ) );
var s = new StringBuilder();
foreach ( var b in bs ) {
s.Append( b.ToString( "x2" ).ToLower() );
}
return s.ToString();
}
}
}

二、ページGZIP圧縮
ページGZIP圧縮は、高性能WEBプログラムを説明するほとんどの方法の一つです.GZIP圧縮を使用すると、サーバから送信されるバイト数を減らすことができ、Webページの速度が速く、帯域幅の使用状況を減らすことができるからです.もちろん、クライアントのブラウザがサポートしているかどうかはここにもあります.したがって、クライアントがGZIPをサポートしている場合は、GZIP圧縮されたコンテンツを送信し、サポートされていない場合は、静的ファイルのコンテンツを直接送信します.幸いなことに、現代ブラウザIE 6.7.8.0、火狐などはGZIPをサポートしています.
この機能を実現するには、上記のApplication_を書き換える必要があります.BeginRequestイベント:
 
  
private void Application_BeginRequest( object sender, EventArgs e ) {
var context = HttpContext.Current;
var request = context.Request;
var url = request.RawUrl;
var response = context.Response;
var path = GetPath( url );
var file = new FileInfo( path );
//
ResponseCompressionType compressionType = this.GetCompressionMode( request );
if ( compressionType != ResponseCompressionType.None ) {
response.AppendHeader( "Content-Encoding", compressionType.ToString().ToLower() );
if ( compressionType == ResponseCompressionType.GZip ) {
response.Filter = new GZipStream( response.Filter, CompressionMode.Compress );
}
else {
response.Filter = new DeflateStream( response.Filter, CompressionMode.Compress );
}
}
if ( DateTime.Now.Subtract( file.LastWriteTime ).TotalMinutes < 5 ) {
response.TransmitFile( path );
response.End();
return;
}
try {
var stream = file.OpenWrite();
response.Filter = new CommonFilter( response.Filter, stream );
}
catch ( Exception ) {
//Log.Insert("");
}
}
private ResponseCompressionType GetCompressionMode( HttpRequest request ) {
string acceptEncoding = request.Headers[ "Accept-Encoding" ];
if ( string.IsNullOrEmpty( acceptEncoding ) )
return ResponseCompressionType.None;
acceptEncoding = acceptEncoding.ToUpperInvariant();
if ( acceptEncoding.Contains( "GZIP" ) )
return ResponseCompressionType.GZip;
else if ( acceptEncoding.Contains( "DEFLATE" ) )
return ResponseCompressionType.Deflate;
else
return ResponseCompressionType.None;
}
private enum ResponseCompressionType {
None,
GZip,
Deflate
}

三、OutputCacheプログラミング方式出力ページキャッシュ
ASP.NET内蔵のOutputCacheキャッシュでは、Webサーバ、プロキシサーバ、ブラウザの3つの場所にコンテンツをキャッシュできます.ユーザがOutputCacheに設定ページにアクセスすると、ASP.NETはMSILの後、output cacheキャッシュに結果を書き込む後、ブラウザに送信し、ユーザーが同じパスのページにアクセスすると、ASP.NETは、Cacheによるコンテンツをそのまま送信.aspxコンパイルおよびMSILの実行プロセスにより,プログラム自体の効率は向上しなかったが,ページ読み込み速度は向上した.
この機能を実現するために、上記のApplication_を書き換え続けます.BeginRequestイベントは、TransmitFileの後、このパスのページをOutputCacheプログラミングでキャッシュします.
 
  
private void Application_BeginRequest( object sender, EventArgs e ) {
//.............
if ( DateTime.Now.Subtract( file.LastWriteTime ).TotalMinutes < 5 ) {
response.TransmitFile( path );
// OutputCache ,
response.Cache.SetExpires( DateTime.Now.AddMinutes( 5 ) );
response.Cache.SetCacheability( HttpCacheability.Public );
response.End();
return;
}
//............
}

四、CommonFilterクラスのViewStateのフィルタリング、NamingContainerのフィルタリング、空白文字列のフィルタリング、ディスクのキャッシュファイルの生成を実現する
我々はresponseに伝えたFilterのStreamオブジェクトはCommonFilterクラスに与えられます.
まず、ディスクを生成するキャッシュファイルを実装するには、まずStreamのWriteメソッドを使用します.コードは以下のとおりです.これらのコードでは、構造関数の初期化、Writeメソッド、Closeメソッドのみが役立ちます.FileStreamフィールドは静的ファイルを生成する操作対象です.
 
  
namespace ASPNET_CL.Code.HttpModules {
public class CommonFilter : Stream {
private readonly Stream _responseStream;
private readonly FileStream _cacheStream;
public override bool CanRead {
get {
return false;
}
}
public override bool CanSeek {
get {
return false;
}
}
public override bool CanWrite {
get {
return _responseStream.CanWrite;
}
}
public override long Length {
get {
throw new NotSupportedException();
}
}
public override long Position {
get {
throw new NotSupportedException();
}
set {
throw new NotSupportedException();
}
}
public CommonFilter( Stream responseStream, FileStream stream ) {
_responseStream = responseStream;
_cacheStream = stream;
}
public override long Seek( long offset, SeekOrigin origin ) {
throw new NotSupportedException();
}
public override void SetLength( long length ) {
throw new NotSupportedException();
}
public override int Read( byte[] buffer, int offset, int count ) {
throw new NotSupportedException();
}
public override void Flush() {
_responseStream.Flush();
_cacheStream.Flush();
}
public override void Write( byte[] buffer, int offset, int count ) {
_cacheStream.Write( buffer, offset, count );
_responseStream.Write( buffer, offset, count );
}
public override void Close() {
_responseStream.Close();
_cacheStream.Close();
}
protected override void Dispose( bool disposing ) {
if ( disposing ) {
_responseStream.Dispose();
_cacheStream.Dispose();
}
}
}
}

次に、正則を使用してView Stateを完全に削除します.
 
  
// ViewState
private string ViewStateFilter( string strHTML ) {
string matchString1 = "type=\"hidden\" name=\"__VIEWSTATE\" id=\"__VIEWSTATE\"";
string matchString2 = "type=\"hidden\" name=\"__EVENTVALIDATION\" id=\"__EVENTVALIDATION\"";
string matchString3 = "type=\"hidden\" name=\"__EVENTTARGET\" id=\"__EVENTTARGET\"";
string matchString4 = "type=\"hidden\" name=\"__EVENTARGUMENT\" id=\"__EVENTARGUMENT\"";
string positiveLookahead1 = "(?=.*(" + Regex.Escape( matchString1 ) + "))";
string positiveLookahead2 = "(?=.*(" + Regex.Escape( matchString2 ) + "))";
string positiveLookahead3 = "(?=.*(" + Regex.Escape( matchString3 ) + "))";
string positiveLookahead4 = "(?=.*(" + Regex.Escape( matchString4 ) + "))";
RegexOptions opt = RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.CultureInvariant | RegexOptions.Compiled;
Regex[] arrRe = new Regex[] {
new Regex("\\s*
" + positiveLookahead1 + "(.*?)
\\s*", opt),
new Regex("\\s*
" + positiveLookahead2 + "(.*?)
\\s*", opt),
new Regex("\\s*
" + positiveLookahead3 + "(.*?)
\\s*", opt),
new Regex("\\s*
" + positiveLookahead3 + "(.*?)
\\s*", opt),
new Regex("\\s*
" + positiveLookahead4 + "(.*?)
\\s*", opt)
};
foreach ( Regex re in arrRe ) {
strHTML = re.Replace( strHTML, "" );
}
return strHTML;
}

ページの空白を削除する方法は、次のとおりです.
 
  
//
private Regex tabsRe = new Regex( "\\t", RegexOptions.Compiled | RegexOptions.Multiline );
private Regex carriageReturnRe = new Regex( ">\\r\
private Regex carriageReturnSafeRe = new Regex( "\\r\
", RegexOptions.Compiled | RegexOptions.Multiline );
private Regex multipleSpaces = new Regex( " ", RegexOptions.Compiled | RegexOptions.Multiline );
private Regex spaceBetweenTags = new Regex( ">\\sprivate string WhitespaceFilter( string html ) {
html = tabsRe.Replace( html, string.Empty );
html = carriageReturnRe.Replace( html, ">html = carriageReturnSafeRe.Replace( html, " " );
while ( multipleSpaces.IsMatch( html ) )
html = multipleSpaces.Replace( html, " " );
html = spaceBetweenTags.Replace( html, ">html = html.Replace( "//html = html.Replace( "//]]>", "" );
return html;
}

以下、ASPを削除する.NETコントロールのゴミUniqueID名称方法:
 
  
// NamingContainer
private string NamingContainerFilter( string html ) {
RegexOptions opt =
RegexOptions.IgnoreCase |
RegexOptions.Singleline |
RegexOptions.CultureInvariant |
RegexOptions.Compiled;
Regex re = new Regex( "( name=\")(?=.*(" + Regex.Escape( "$" ) + "))([^\"]+?)(\")", opt );
html = re.Replace( html, new MatchEvaluator( delegate( Match m ) {
int lastDollarSignIndex = m.Value.LastIndexOf( '$' );
if ( lastDollarSignIndex >= 0 ) {
return m.Groups[ 1 ].Value + m.Value.Substring( lastDollarSignIndex + 1 );
}
else {
return m.Value;
}
} ) );
return html;
}

最後に、上記のフィルタリング方法をCommonFilterクラスのWrite方法に統合します.
 
  
public override void Write( byte[] buffer, int offset, int count ) {
// buffer
byte[] data = new byte[ count ];
Buffer.BlockCopy( buffer, offset, data, 0, count );
string html = System.Text.Encoding.UTF8.GetString( buffer );
//
//
//
html = NamingContainerFilter( html );
html = ViewStateFilter( html );
html = WhitespaceFilter( html );
byte[] outdata = System.Text.Encoding.UTF8.GetBytes( html );
//
_cacheStream.Write( outdata, 0, outdata.GetLength( 0 ) );
_responseStream.Write( outdata, 0, outdata.GetLength( 0 ) );
}

五、キャッシュ破壊
以上のプログラムの実装により,ウェブページはクライアントにキャッシュされ,ユーザがウェブサイトがキャッシュされたページにアクセスすると,ページは0要求の速度でロードされる.しかし、バックグラウンドでデータが更新されると、フロントユーザーは最新のデータをタイムリーに見ることができないため、このような状況を変更するには、キャッシュを破壊する必要があります.上記の手順に従って、キャッシュを破壊するには2ステップしかかかりません.サーバ上の一時ファイルを更新し、OutputCacheのページを削除します.
サーバ上のファイルを更新するには、このファイルを削除するだけでいいです.あるユーザーが初めてページにアクセスしたときに自動的に生成されます.もちろん、プログラムで削除してから生成することもできます.
 
  
//
foreach ( var file in Directory.GetFiles( HttpRuntime.AppDomainAppPath + "Temp" ) ) {
File.Delete( file );
}

OutputCacheに関連付けられたキャッシュ・アイテムを削除するには、次のようなコードがあります.このメソッドのパラメータを保証するだけです.ページの絶対パスが正しいことを意味し、パスは.../を使用できません.相対パス:
 
  
//
HttpResponse.RemoveOutputCacheItem( "/Default.aspx" );

これにより、1ページのパフォーマンスを実現し、ロード速度の向上に重点を置いたいくつかの方法が実現し、皆さんに役に立つことを願っています~!