最大的差别在testpage_inlinepage_aspx有个方法:__Render__control1
在这个方法中,页面的内容将直接被写入到HtmlTextWriter对象中。
还有一点我要告诉您:每个Control的输出最后还是要将自己的显示代码写入到HtmlTextWriter对象中。
因此,从这里就可以明显地看出testpage_inlinepage_aspx的执行速度要快很多,
因为:
1. 它没有服务器控件。
2. 不再需要递归循环每个控件,每个控件的生命周期的调用开销也节省了。
3. 不用再创建那些服务器控件对象,GC的压力会小很多。
4. 输出方式更高效。
通过前面的分析,您现在明白了为什么二个页面的执行速度相差6倍了原因了吧。
好像还有一点没有解释:__Render__control1如何被调用?
我们都知道:以ASPX页面为代表的WebForm编程模型在执行时有一个特点:递归循环每个控件。
页面是在Render阶段输出的,页面的HTML代码也是在那个阶段输出到HtmlTextWriter对象中的。
可是,testpage_inlinepage_aspx没有任何控件,那又该如何递归呢?
的确,很多书籍以及技术资料都是说:在Render阶段会递归循环每个控件并调用控件的Render方法。
其实这种说法是不准确的。Control的Render方法在运行时,会调用下面这个方法:
- internal void RenderChildrenInternal(HtmlTextWriter writer, ICollection children)
- {
- if ((this.RareFields != null) && (this.RareFields.RenderMethod != null))
- {
- writer.BeginRender();
- this.RareFields.RenderMethod(writer, this);
- writer.EndRender();
- }
- else if (children != null)
- {
- foreach (Control control in children)
- {
- control.RenderControl(writer);
- }
- }
- }
这段代码中,有个重要的if...else...判断,简单说来,就是说要不要调用前面所说的__Render__control1方法。
从代码可以看出,如果是进入了if语句块,则不用递归循环每个控件并调用控件的Render方法。
那么如何能进入if语句块呢?
答案是:调用Control.SetRenderMethodDelegate方法。
testpage_inlinepage_aspx的编译生成代码中就有这个调用。
对于这个方法,MSDN的解释很含糊:
此 API 支持 .NET Framework 基础结构,不适合在代码中直接使用。 分配事件处理程序委托,以将服务器控件及其内容呈现到父控件中。 |
498)this.width=498;'' onmousewheel = ''javascript:return big(this)'' border="0" alt="" width="31" height="11" src="http://images.myeducs.cn/files/uploadimg/20120312/144240756.gif" />
测试用例3:InlineUserControl.ascx
在测试用例3中,我将页面中用于输出的代码移到一个用户控件中。
用户控件的代码此处省略,与测试用例2的代码基本上一致。编译后的结果也基本差不多。
测试代码:
- [Action]
- public object Test3(string callTimes)
- {
- int count = 0;
- int.TryParse(callTimes, out count);
- if( count <= 0 )
- return count;
- // 先执行一次,排除编译时间
- string html = MyMVC.UcExecutor.Render("/UserControl/InlineUserControl.ascx", null);
- Stopwatch watch = Stopwatch.StartNew();
- for( int i = 0; i < count; i++ )
- html = MyMVC.UcExecutor.Render("/UserControl/InlineUserControl.ascx", null);
- watch.Stop();
- return watch.Elapsed.ToString();
- }
当