Wil*_*eys 5 c# asp.net asp.net-mvc performance placeholder
版本2
我已经更新了原始代码,考虑到write方法以块的形式从页面流式传输HTML.
正如所指出的那样'因为您不能保证在写入时将"THE_PLACEHOLDER"写入连续的字节块中.您可以在一次写入结束时获得"THE_PLACEH",并在下一次开始时获得"OLDER".
我已经通过将流的完整内容放在Stringbuilder中并执行Close方法所需的任何更新来解决此问题.
这样做后,我再次在下面问同样的问题....
我正在使用CMS,它只是用CMS文本替换占位符.
我有以下工作正常工作.
我已经覆盖了IHttpModule
public class CmsFilterHttpModule : IHttpModule {
// In the Init method, register HttpApplication events by adding event handlers.
public void Init( HttpApplication httpApplication ) {
httpApplication.ReleaseRequestState += new EventHandler( this.HttpApplication_OnReleaseRequestState );
}
/// <summary>
/// HttpApplication_OnReleaseRequestState event handler.
///
/// Occurs after ASP.NET finishes executing all request event handlers.
/// This event causes state modules to save the current state data.
/// </summary>
private void HttpApplication_OnReleaseRequestState( Object sender, EventArgs e ) {
HttpResponse httpResponse = HttpContext.Current.Response;
if ( httpResponse.ContentType == "text/html" ) {
httpResponse.Filter = new CmsFilterStream( httpResponse.Filter );
}
}
public void Dispose() {
//Empty
}
}
Run Code Online (Sandbox Code Playgroud)
和MemoryStream
public class CmsFilterStream : MemoryStream {
private Stream _responseStream;
private StringBuilder _responseHtml;
public CmsFilterStream( Stream inputStream ) {
_responseStream = inputStream;
_responseHtml = new StringBuilder();
}
/// <summary>
/// Writes a block of bytes to the current stream using data read from a buffer.
/// </summary>
/// <param name="buffer">The buffer to write data from.</param>
/// <param name="offset">The zero-based byte offset in buffer at which to begin copying bytes to the current stream.</param>
/// <param name="count">The maximum number of bytes to write.</param>
public override void Write( Byte[] buffer, Int32 offset, Int32 count ) {
if ( buffer == null ) { throw new ArgumentNullException( "buffer", "ArgumentNull_Buffer" ); }
if ( offset < 0 ) { throw new ArgumentOutOfRangeException( "offset", "ArgumentOutOfRange_NeedNonNegNum" ); }
if ( count < 0 ) { throw new ArgumentOutOfRangeException( "count", "ArgumentOutOfRange_NeedNonNegNum" ); }
if ( buffer.Length - offset < count ) { throw new ArgumentException( "Argument_InvalidOffLen" ); }
String bufferContent = UTF8Encoding.UTF8.GetString( buffer, offset, count );
_responseHtml.Append( bufferContent );
}
public override void Close() {
_responseHtml.Replace( "THE_PLACEHOLDER", "SOME_HTML" );
_responseStream.Write( UTF8Encoding.UTF8.GetBytes( _responseHtml.ToString() ), 0, UTF8Encoding.UTF8.GetByteCount( _responseHtml.ToString() ) );
_responseStream.Dispose();
base.Close();
}
}
Run Code Online (Sandbox Code Playgroud)
以及Web.config中的以下内容
<system.webServer>
<modules>
<remove name="CmsFilterHttpModule" />
<add name="CmsFilterHttpModule" type="{MY_NAMESPACE}.CmsFilterHttpModule" />
</modules>
</system.webServer>
Run Code Online (Sandbox Code Playgroud)
这确实可行.
我的问题是,在我开始向后工作之前,这是最好的地方.
此方法正在替换已完成输出上的文本.
我正在寻找从管道角度替换此文本的最快方法.
目前忽略了String.Replace/Stringbuilder的速度以及其他各种方法.我看到优化稍微进一步.
我还没有通过整个管道进行调试,但是我猜这个页面必须是从不同的部分构建的,即布局,视图部分等等,也许更快地替换这些部分的文本.
另外还有任何问题
String bufferContent = UTF8Encoding.UTF8.GetString(buffer);
Run Code Online (Sandbox Code Playgroud)
当使用其他语言日语,中文等
我还必须补充说,我正在尝试将此作为一个单独添加的代码,尽可能少地触及用户站点MVC代码.
要处理完整的响应,而无需处理调用之间的状态来编写实现,不需要重写该Write方法,只Close需要该方法,因为您首先需要在转换之前捕获所有字节。这是一个有效的实现:
public class CmsFilterStream : MemoryStream {
private Stream _responseStream;
public CmsFilterStream( Stream inputStream ) {
_responseStream = inputStream;
}
public override void Close() {
var allHtml = UTF8Encoding.UTF8.GetString(this.ToArray()); // get ALL bytes!!
allHtml = allHtml.Replace("THE_PLACEHOLDER", "SOME_HTML");
var buf =UTF8Encoding.UTF8.GetBytes(allHtml);
_responseStream.Write(buf,0, buf.Length);
_responseStream.Flush(); // I assume the caller will close the _responseStream
base.Close();
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个幼稚的实现。您可以优化替换代码并写入流,但只有当您的性能测量表明这种和平的代码位于热路径上时,我才会优化它。
| 归档时间: |
|
| 查看次数: |
797 次 |
| 最近记录: |