駁sp1234之[如果你必须开发交互式页面,ViewState越大可能意味着越有本事]一貼

boblaw 2008-06-04 09:35:47
那個貼子太長,我雖然有回復,不過應該沒有幾個人注意到我的不同觀點,所以開一貼討論。歡迎sp1234及其他有興趣的朋友進來討論。如果回復較多,再加分。
原貼http://topic.csdn.net/u/20080530/22/ef0d36a4-6bd4-4eba-9743-b56f080b2161.html

下面是sp1234的觀點及代碼:
如果你有一个非常酷的页面,页面上很多东西自动地响应用户操作而展现丰富的变化,你的ViewState是很有可能达到200K的。

这里是我将ViewState持久化保持在服务器端的代码,这样ViewState不占用网络带宽,因此其存取只是服务器的磁盘读取时间。并且它很小,可以说是磁盘随便转一圈就能同时读取好多ViewState,因此可以说“不占时间”。为了再“不占磁盘时间”,我还使用了缓存。

不使用Session,因为它会“丢失”。ViewState保存在磁盘上,即使服务器重新启动,也不会丢失页面状态。
这可以确保绝对稳定可靠地工作。以后请放心使用ViewState,把交互式页面提高水平才是最重要的,不要纠缠在“ViewState太大”上。实际上,由于页面设计不够酷,交互变化看上去不够丰富,ViewState实在是太小太小了。

如果你使用了它有效提高了复杂交互页面的效率,可以说一下提高了多少?!如果你觉得没用,也可以说一下在什么情况下没用。


protected override object LoadPageStateFromPersistenceMedium()
{
var viewStateID = (string)((Pair)base.LoadPageStateFromPersistenceMedium()).Second;
var stateObject = Cache[viewStateID];
if (stateObject != null)
return stateObject;

var fn = this.Server.MapPath("~/App_Data/ViewState/" + viewStateID);
var stateStr = File.ReadAllText(fn);
return new ObjectStateFormatter().Deserialize(stateStr);
}

protected override void SavePageStateToPersistenceMedium(object state)
{
var viewStateID = (DateTime.Now.Ticks + this.GetHashCode()).ToString(); //产生离散的id号码
Cache.Insert(viewStateID, state);
ThreadPool.QueueUserWorkItem(obj =>
{
var value = new ObjectStateFormatter().Serialize(state);
var fn = this.Server.MapPath("~/App_Data/ViewState/" + viewStateID);
File.WriteAllText(fn, value);
});
base.SavePageStateToPersistenceMedium(viewStateID);
}


下面是我的觀點:
这么多人跟贴,我也来发表下意见,探讨一下。

总体来说,LZ的思路对于某些场景是非常有用的,但是绝对不宜大量推广,一些还不能够分清利弊的程序员更不应该像楼主所说的“以后请放心使用ViewState,把交互式页面提高水平才是最重要的,不要纠缠在“ViewState太大”上”。

因为这个方法虽然节省了客户端与服务器间的带宽传输,但是加大了服务器的负荷(包括服务器的CPU负荷、其他性能消耗以及磁盘空间,特别是访问量大的站点绝不应该这样使用。另外,LZ实现的方法值得商榷,破坏了ASP.NET已经设计好的架构(视图保存及读取部分).

细述如下(针对楼主116楼的最终写法):
1. 每次页面运行都至少要写缓存一次,读缓存了次,写磁盘一次,来保存或读取视图。
首先,每次都要存缓存,尽管LZ是为了获得从缓存中读取视图的性能提升,但这样操作缓存是否太频繁了?虽然读的时候提升了速度,但是存的时候却损失了保存缓存所消耗的CPU以及缓存空间。
其次,每次使用磁盘来保存视图,也是个问题。碰盘的操作有瓶颈,这是无法回避的问题,使用线程,即使是使用.NET内置的线程池,但终究还是增加了系统及CPU的开销,关于线程,在第2点中还会讲到。
对于一个访问量不大的站点,上述的这些问题不会很明显,但是一旦访问量大的话,服务器的性能就会有影响了,并发响应能力也会降低。

2. 关于线程
线程性能问题,上面已经提到,就不再说了。
由于楼主使用的是.NET内置的线程池,线程池的大小是有限制的,请设想这样一种场景:当客户端请求服务器上的一个页面,保存视图时,在排队等待线程池时却没有可用的线程。而此时客户端已经回发过来,需要加载视图状态,恰巧由于缓存机制把缓存的视图清空,而这时上一次的视图却还没有保存到磁盘!
这时,这个视图机制就等同于失效了。尽管一般情况下,发生这种情况的可能性不大,但是当并发访问量大时,绝不能排除它的发生。

3. 关于SavePageStateToPersistenceMedium和LoadPageStateFromPersistenceMedium的实现,也就是我在之前所说的“破坏了ASP.NET已经设计好的架构”
直接复制MSDN上的资料:

LoadPageStateFromPersistenceMedium 方法使用 PageStatePersister 属性所引用的 System.Web.UI.PageStatePersister 对象的 Load 方法来为 Page 对象加载任何保存的视图状态信息。

ASP.NET 包括 PageStatePersister 类的两个子类:在 ASP.NET 页包含的隐藏字段中保存状态信息的 HiddenFieldPageStatePersister 类和在与请求关联的 Session 对象中保存状态的 SessionPageStatePersister 类。

若要在您选择的位置保存状态,应创建 PageStatePersister 类的新子类,它可将状态保存并加载到您所选择的持久性介质中。有关创建新的 PageStatePersister 对象的示例,请参见 PageStatePersister 类。

使用 .NET Framework 1.0 版或 1.1 版时,如果要从隐藏字段外的其他任何位置加载 Page 状态,则请重写此方法。如果选择这样做,还必须重写 SavePageStateToPersistenceMedium 方法。


SavePageStateToPersistenceMedium 方法使用 PageStatePersister 属性所引用的 System.Web.UI.PageStatePersister 对象的 Save 方法存储页的视图状态和控件状态信息。

ASP.NET 包括 PageStatePersister 类的两个子类:在 ASP.NET 页包含的隐藏字段中保存状态信息的 HiddenFieldPageStatePersister 类和在与请求关联的 Session 对象中保存状态的 SessionPageStatePersister 类。注意,使用 SessionPageStatePersister 类时,隐藏的 VIEWSTATE 字段仍将像用于确定回发时那样呈现。

若要在您选择的位置保存状态,应创建 PageStatePersister 类的新子类,它可将状态保存并加载到您所选择的持久性介质中。有关创建新的 PageStatePersister 对象的示例,请参见 PageStatePersister 类。

使用 .NET Framework 1.0 版或 1.1 版时,如果要从隐藏字段外的其他任何位置保存 Page 状态,则请重写此方法。如果选择这样做,还必须重写 LoadPageStateFromPersistenceMedium 方法。
...全文
1443 151 打赏 收藏 转发到动态 举报
写回复
用AI写文章
151 条回复
切换为时间正序
请发表友善的回复…
发表回复
zhubo006 2010-09-28
  • 打赏
  • 举报
回复

顶起,个人支持 SP1234
cfvgodot 2010-01-26
  • 打赏
  • 举报
回复
[Quote=引用 118 楼 popeyepower 的回复:]
我是不认同这样的做法.
首先viewstate是个性化的东西.每个用户在每个页面就产生一份,很有可能用户两次访问同一个页面的viewstate就完全不一样了...你存得完啊...存了又删,删了又存,就算你再优化算法,对这种事情做缓存你的命中率又能有多少.
其次缓存不是用来存viewstate的,无数的视图...控件都要用到缓存,你要说你又做前端群集,还每个前端都8G内存在那里候着...就当我没说.
第三不是说磁盘容量占用多少的问题,磁盘访问速度本来就很慢.

总之不建议大量使用viewstate,做企业级的,访问量相对低,viewstate能提高交互性,可以多用用,也不是说滥用..做门户级的,还是省了吧,能少用尽量少用.
[/Quote]

VIEWSTATE这鸟东西即便做MIS我也是不会用的,交互性依然要AJAX....

PS:可能老大们在一个豆腐渣工程上吵起来了,我就看热闹的。。。
lg9925 2010-01-11
  • 打赏
  • 举报
回复
mark
nick207 2009-08-29
  • 打赏
  • 举报
回复
关注中
sujo 2008-08-06
  • 打赏
  • 举报
回复
对于并发量不大的企业Web应用而言,确实过分了担心这些问题了。毕竟做大型网站的人占少数,做中小型网站的多,做企业Web应用开发的更多。
leer168 2008-06-06
  • 打赏
  • 举报
回复
mark
qiangv 2008-06-06
  • 打赏
  • 举报
回复
mark

对viewstate反感,宁可自己控制。
NqIceCoffee 2008-06-06
  • 打赏
  • 举报
回复
ViewState也有它的好处。但滥用感觉就不好了。

还有,MVC出来了,不喜欢ViewState的有另一种选择了

呵呵,祝大家愉快编程
heguo 2008-06-05
  • 打赏
  • 举报
回复
又顶这么多了??
抵制ViewState?我听着怎么跟"抵制Asp.NET"差不多.
另:
我记得Cache有个过期的东东,虽然不太好用,或许可以延迟写磁盘.
IIS本身就用了线程池技术,可能不同IIS版本使用方式不太一样。
dsclub 2008-06-05
  • 打赏
  • 举报
回复
谁赢了?

用不用缓存症结是什么?性能么?记得sp1234当初说过类似“不要只是说很多、大概、估计之类的,拿出切实的分析结果”

我想也是,双方都按自己的想法来个benchmark,看看结果。

理论看多了晕,我等初学者更会为失去方向而迷惑。
liubin911 2008-06-05
  • 打赏
  • 举报
回复
搬个板凳先
ojekleen 2008-06-05
  • 打赏
  • 举报
回复
[Quote=引用 126 楼 syeerzy 的回复:]
很精彩,不过中间夹杂个别不知轻重的人,美中不足.


都说得很有道理 , 不过从我个人经验看, 我比较倾向于sp1234的观点. 事实上我觉得ViewState被太多人放到反面去了想要 "尽量减少" .

[/Quote]

闻道有先后,术业有专攻,没必要含沙射影
ojekleen 2008-06-05
  • 打赏
  • 举报
回复
呵呵,谢谢歌丸,当时既然没看明白,晕死。
kingmax54212008 2008-06-05
  • 打赏
  • 举报
回复
sounds good.
add to my favorite.
zahhb 2008-06-05
  • 打赏
  • 举报
回复
我认真看了sp1234的文章,也仔细看了楼主的意见,
我觉得sp1234的做法确实节省了客户端与服务器间的带宽传输,这点楼主也是同意的,至于楼主
说影响到服务器性能,这也是肯定的,但影响到底有多大才是关键,如果楼主能用测试数据说明
sp1234的做法确实给服务器带来了太大的压力,那才能说明你的观点是对的。如果测试数据显示sp1234的
做法给服务器带来的压力并不是很大,那楼主就是多虑了。至于msn上的那段话,不能作为论据。
游北亮 2008-06-05
  • 打赏
  • 举报
回复
标记标记,看精华
  • 打赏
  • 举报
回复
其实我主要是在说明这个架构带来的上百倍以上的速度提高,而在服务器本地执行速度提高一点点,并没有太去讨论。
  • 打赏
  • 举报
回复
有一个问题,也是一个大背景:ViewState是在每次一页面回发时漫游于服务器和千里万里之外浏览器之间,通过跋涉千山万水,挤占每一个网络设备的有效带宽,比服务器本地磁盘“瓶颈”细上万倍。
wzy_love_sly 2008-06-04
  • 打赏
  • 举报
回复
顶 学习
叶子 2008-06-04
  • 打赏
  • 举报
回复
关注一下
加载更多回复(129)

62,046

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧