更改Ҏ:
打开 C:\Documents and Settings\Administrator\Local Settings\Application Data\Microsoft\VisualStudio\8.0\browsers.xml
一、异步IO
对于应用E序而言Q有两种cd的IO调用Q即同步IO
与异步IO。其本质的区别是Q同步IO会block当前的调用线E,而异步IO则允许发起IOh的调用线El执行,{到IOh被处理后Q会通知调用
U程。在windowsq_上,应用E序可以调用CreateFile API,
q过讄FILE_FLAG_OVERLAPPED标志来决定是否发起异步IOh?br> 对于异步的IOhQ其最大的好处是:慢速的IOh相对于应用程序而言是异步执行,q样可以极大提高应用E序的处理吞吐量。发起IOh的应用程序需要关心的是IO执行完成的结果,而不必忙{IOh执行的过E?br>
事实上,无论对于同步IOQ还是异步IO,当IOh发送到device driver后,device
driver的执行L异步?当它接到IOh之后QM马上q回lIO System。而IO
System是否立即q回l调用线E,则取决于FILE_FLAG_OVERLAPPED标志的设|?如下图:
二、异步IO的同步问题?br>
我们使用异步IOQ是Z提高应用E序的处理吞吐量。但是,当异步IO不再异步Ӟ无论你是否设|FILE_FLAG_OVERLAPPED标志Q,应用
E序的性能会受到极大的影响。根据Microsoft Knowledge Base 156932,
在下列几U情况下Q异步IO会失d的异步性,而表现出同步的性质Q?br>1Q如果文件用了NTFS compression压羃Q则system driver不会异步地存取这L文g?br>2Q扩展文仉度的IO操作不会是异步操作?br>3QCache机制。如果IO操作使用了file system cacheQ则q样的IO操作会被当成同步IO,而非异步IO?br>即你用了FILE_FLAG_OVERLAPPED标志。在q种情况下,
a.如果需要读取的数据已经在Cache里,那么I/O drivers会认LIOh可以被立卛_理,其结果是ReadFile 或者WriteFile调用q回TRUEQ表C是Q同步处理完成?br>b.
如果需要读取的数据不在Cache里,windows NT的file
system是用page-faulting机制来实现cache理Q而page-faultingL被同步处理, Windows
NT没有提供异步的page-faulting机制。的, file system
driver使用了线E池来缓解这一问题Q但是,当应用程序发LIOh_多时Q线E池q是不能应付的?br> 在我们开发基于异步IO应用E序Ӟ应该避免上述问题的出玎ͼ因ؓ它们会ɽE序的性能大打折扣?br>那么Q对于Cache,我们如何避免呢?{案是:请用FILE_FLAG_NO_BUFFERING标志。这个标志会使异步IO真实地异步执行?br>三、性能的测试数据(仅供参考)?br> 我在我的机器上,单地对用FILE_FLAG_NO_BUFFERING标志的异步IO,与不使用FILE_FLAG_NO_BUFFERING标志的异步IOq行了对比?br>操作Q顺序读?G的文件?br>x轴表C:每次d的字节数Q单位:K/每次Q?br>Y轴表C:d完成所需要的旉。(单位Qmillisecond)
注意Q每ơ测试读取的内容L是相{的Q?000MQ?br>例如Q如果每ơ读?28k,则需要读?000?128k*8000 = 1000M)?br>如果每次d256k,则需要读?000?256k*4000 = 1000M)?
_红色的U没有用FILE_FLAG_NO_BUFFERING标志,而黄色的U用了FILE_FLAG_NO_BUFFERING标志?/p>
从以上的数据,我们可以得出以下l论:
1) 当用FILE_FLAG_NO_BUFFERING标志Q应用程序的性能会极大提高,大概?0%的提高?br>2Q?
在用异步IO的时候,q有一个注意的问题是:当你每次d的字节数增大的时候,性能也会提高。尤其在于1024kӞ当增大次d的字节数Q性能都有
明显的提高。在混合了网l传输等复杂因素的应用程序开发过E中Q徏议将该D|ؓ可配|的参数Q通过调整该参敎ͼ使你的应用达到最好的性能?br>
参考资料:
1Q?nbsp;Microsoft Knowledge Base 156932
2) Microsoft Windows Internals, Fourth Edition.
1.2 MVC架构
MVC最初是在Smalltalk-80中被用来构徏用户界面的。M代表模型Model, V代表视图 ViewQ?C代表 控制器Controller?br>MVC的目的是增加代码的重用率Q减数据表达,数据描述和应用操作的耦合度?同时也得Y件可l护性,可修复性,可扩展性,灉|性以及封装性大大提高?br>单用L应用通常是以事g驱动的用L面ؓl织l构的。开发h员用一个界面工L了一个用h口界面,然后~写代码Ҏ用户输入L行相应的动作Q许多交互式的开发环境鼓p么做Q因为它先有界面然后再有功能。一些Y件设计模式策略是q样的,然后l常固定后的代码融入最后的pȝ当中。导致的l果是Q程序组l围l用L面元素和用户在那些界面元素上的动作,数据的存储,应用的功能以及用来显C的代码都杂乱无章的~绕在一赗在单用Lpȝ里代码结构是可以q样的,因ؓpȝ需求不会频J变化。但是对一个大的系l如大型WebpȝQ或电子商务pȝ来说׃太适用了?br>通过把数据模式从各种可以被存取和控制的数据中分离出来可以改善分布式系l的设计。MVC设计模式׃部分l成。模型是应用对象Q没有用L面。视图表C它在屏q上的显C,代表向用户的数据。控制器定义用户界面对用戯入的响应方式Q负责把用户的动作{成针对Model的操作。Model 通过更新View的数据来反映数据的变化?br>三者关pd图:
2.2 Composite模式
MVC的一个重要特征就是View可以嵌套。嵌套的l合视图可用于Q何视囑֏用的地方Q而且可以理嵌套视图。这U思想反映出将l合的视图与其组件^{对待的设计。这U设计思想在面向对象领域内被描q成为Composite的设计模式?br>模式cdQComposite模式是对象型模式Q同时它也是l构型模式?br>模式目的Q将对象l合成树形结构以表示"部分-整体"层次l构。Composite使组合对象的使用和单个对象的使用h一致性?br>模式l构Q?br>
?. Composite模式的结构图
效果Q?br>1. 定义了包含简单对象和l合对象的类层次l构。简单对象可以被l合到复杂对象中Q而组合的对象可以再被l合。这样客L代码中用到简单对象的地方都可以用组合对象?br>2. 化客L代码。客L不用知道某对象是单对象还是组合对象,可以以一致的方式使用q些对象?br>3. 更容易增加新cd的组件。新的组件可以方便地加入已有l合对象中不用改变客L代码?/p>
2.3 Strategy模式
MVC的另一重要特征是可以在不改变View的情况下改变View对用戯入的响应方式。这对一个经帔R要变更响应逻辑的系l来说是非常重要的。MVC把响应逻辑装在Controller中。有一个Controller的类层次l构Q可以方便地对原有Controller做适当改变Q创建新的Controller。View使用Controller子类的实例来实现一个特定的响应{略。要实现不同的响应策略,只要用不同种cȝController实例替换卛_。还可以在运行时刻通过改变View的Controller来改变View对用戯入的响应{略。这UView-Controller的关pL被描qCؓStrategy的设计模式的一个例子?br>模式cdQStrategy模式是对象型模式Q同时它也是行ؓ型模式?br>模式目的Q定义一pd的算法,q且把它们封装v来,使它们可以互相替换,使得法可以独立于用它的客L而变化?
模式l构Q?br>
?. Strategy模式的结构图
效果Q?br>1. StrategycdơؓContext定义了可重用的相关算法或行ؓ?br>2. 替代l承的方法。如果直接承ContextQ给以不同的行ؓQ会行为加到Context中,从而将法的实CContext混合hQContext难以理解Q维护和扩展Q而且不能动态地改变法。将法装在独立的Strategyc,可以使得法独立于Context改变Q容易切换扩展?br>3. 可以提供相同行ؓ的不同实现?br>4. 客户端必M解Strategy之间有何不同?br>5. Context和Strategy之间的通信开销?br>6. 增加了对象的数目?/p>
3. MVC?Webpȝ中的应用
现在的一些基于Web的分布式pȝ如B2B电子商务pȝQ就适合采用MVC架构?br>通过分析Q从高层ơ的角度可以一个应用的对象分ؓ三类。一cd是负责显C的对象Q一cd象包含商业规则和数据Q还有一cd是接收请求,控制商业对象d成请求。这些应用的昄是经帔R要变换的Q如|页的风|色调Q还有需要显C的内容Q内容的昄方式{。而商业规则和数据是相对要E_的。因此,表示昄的对象Viewl常需要变化的Q表C商业规则和数据的对象Model要相对稳定,而表C控制的Controller则最E_?br>通常当系l发布后QView对象是由工QHTML/JSP设计人员或者系l管理员来负责管理的。Controller对象由应用开发h员开发实施,商业规则对象和商业数据对象则由开发h员,领域专家和数据库理员共同完成的。显C逻辑在Web层或客户端控Ӟ可以是Servlet 或JSPQ动态地生成Html。一般来说采用JSP要比采用Servlet要好。JSP更好地将代码与Html部分分开Q有利于面设计人员和代码开发h员的分离Q提高效率。同时JSP可以完成所有Servlet完成的功能,实际上JSP最l也转换成一个Servlet。与控制有关的对象存在于pȝ的每一个层ơ,协调跨层动作。包含商业规则和数据的对象存在于EJB层(以EJBZ心的模式Q或Web层(以WebZ心的模式Q?br>
3.1 View在Webpȝ中的应用
View代表pȝ的显C,它完全存在于Web层。一般由JSP, Java Bean和Custom Tagl成。JSP可以动态生成网内容,Custom Tag 更方便了使用Java BeanQ而且它可以封装显C逻辑Q更有利于于模块化和重用。一些设计良好的Custom Tag可以在多个JSP甚至可以在不同的pȝ里重复用。Java Bean用来控制JSP和Model对象。JSP通过Java Bean 来读取Model对象中的数据QModel和Controller对象则负责对Java Bean的数据更新。一般来_可以先要设计出所有可能出现的屏幕Q即用户使用pȝ时可以看到的所有内宏V然后根据这些内容,扑և公共部分Q静态部分和动态变化部分。可以考虑使用模板ҎQ把公用的内容单独生成JSPQ需要变化的也各自生成Html或JSP, ׃个模板JSP, 把这些不同部分动态地引入QincludeҎQ。还有一个要考虑的问题就是屏q的选择问题Q当处理完用戯求,模板被自动调用来昄Q这个显CZ定要知道用户兛_的屏q是有哪些部分组成。所以可以考虑把所有屏q的定义攑֜一个集中的文g里,如一个java文g或文本文件。由于考虑到屏q定义文件将来的变更可能性,最好用文本文件如一个XML文gQ这样将来更改不用重新编译。可以根据用戯入的URL和参数可以映到某一个结果屏q,当然有可能还要根据动作的执行l果选择不同的结果屏q内宏V所以需要一个请求与资源的匹配文ӞXMLQ,如果一个URLh有几U不同结果,则要在该文g中指明是否需要流控制Q一Ucontroller对象Q以及不同流向的对应屏幕?br>
3.2 Model在Webpȝ中的应用
Model对象代表了商业规则和商业数据Q存在于EJB层和Web层。在J2EE的规范中Q系l有些数据需要存储于数据库中Q如用户的̎号信息(account modelQ,公司的数?company model){,也有一些不需要记录在数据库里的,如某用户览的当前品目?catalog model)Q他的购物内?shopping cart model){。这些model数据存在于哪一层要Ҏ它们的生命周期和范围来决定。在Web层有HttpSession和ServletContext及Java Bean对象来存储数据,在EJB层则有EJB来存储数据和逻辑。Web层的Java Bean的model对象存储了EJB层model对象的数据的拯。因为EJB层有很多不同的model对象Q所以Web层可以通过一个ModelManager来控制EJB层的各model对象Q在ModelManger中可以封装用后台model对象的方法?br>在EJB层把所有的数据和规则都模式化ؓEJB也是不恰当的。如可以把存取数据库的对象模式化为DAO对象。DAO中可以封装与具体数据库的交互l节Q如可以d不同的表Q多个数据库Q甚臛_U数据库。如定单的model对象可以是一个OrderDAO, 它可能要同时处理Order表,OrderStatus表和OrderItemLines表?br>q有可以考虑使用Value对象。一个Value 对象可以装q程对象Q因为每一个读q程对象的属性都可能是一个远E过E调用,都会耗费|络资源。可以在EJB的远E对象中使用Value对象. 在远E对象中一ơ性得到Value对象来得到所有属性的倹{?/p>
3.3 Controller在Webpȝ中的应用
Controller对象协调Model与ViewQ把用户h译成系l识别的事g。在Web层,一般有一个MainServlet(或Main.jsp)Q接收所有请求,它可以调用屏q流理器(ScreenFlowMangerQ决定下一个屏q。一般还有一个请求处理器RequestProcessorQ包含所有请求都需要做的处理逻辑Q如把请求翻译成pȝ事gQRequestToEventQ。请求处理器通常q包含一个代理对象ClientControlWebImplQ它是EJB层的逻辑处理的在Web层的代理。在EJB层,有一个ClientController提供Web 层对EJB层的只读讉K。还有一个StateMachine用来建立和删除ejbQ处理Web层送来的事件?br>Controllerq有一个重要的功能是同步View和Model的数据。在ModelManger中包含一个ModelUpdateMangerQ它把系l事件{换ؓ一个Model的集合,x有需要同步的ModelQ然后通知Listenersd同步操作?br>
4. l束?/strong>
q年来随着互联|技术的发展和新的商业模式的出现Q必然会出现大量ZWeb的应用系l。对于如何设计这些系l的体系l构Q也逐渐有了一些统一的认识,最主要的是的就是其体系l构要合理,开放。需求永q会比技术和设计思想发展快,要ɞ来pȝ的升U所付出的代h,研究软gpȝ的体pȝ构还是非常很用和有必要的?br>
参考文?/strong>
[1] 设计模式Q作者Erich Gamma {,ISBN 7-111-07575-7, 机械工业出版C?2000.9
[2] Core J2EE Patterns, 作者Deepak Alurm {? ISBN 0-13-064884-1, Sun Microsystems Inc, 2001q?br>[3] Designing Enterprise Applications with the J2EETM Platform, 作者Nicholas Kassem {, Sun Microsystems, Inc. 2000q?br>
² 下一个将执行的方法是AddParsedSubObjectҎQ这个方法将d所有独立的控gq把面l成一个控仉合树Q这个方 法经常被一些高U的面模板解决Ҏ(Page Template Solutions)重写以便d面内容到页面模板(Page TemplateQ中一些特D的控g中。这个方法递归应用到所有的面控g及相应的的每个子控gQ所有的控g都是在这个方法中开始最早的初始化?/p>
² 面cM下一个将执行的方法是DeterminePostBackMode。这个方法允许您修改IsPostBack的值及相关的事件。如果您 需要从数据库中加蝲ViewStateq个Ҏ特别有用,因ؓViewState只有在IsPostBack为真的情况下才会q行恢复。返回空会D 强制执行非回传,q回Request.Form则强制执行一个回传。除非在Ҏ情况下,否则q不L作这个,因ؓq个q会影响其他的事件?/p>
² 下一个将要执行的Ҏ是OnInitҎQ一般这是第一个真正被使用的方法。这个方法触发时Q所有页面定义中的控件执行初始化Q这意味着所有在 面中定义的值应用到相应的控件上。不q,ViewState和传回的D不会应用到控件上Q因此,M被代码或用户改变的D没有被恢复到控g上。这? Ҏ通常是最好的创徏、重创徏动态控件的好地斏V?br>l 恢复及加?br>² 下一个方法, LoadPageStateFromPersistenceMedium只会在页面被回传的时候才会被执行。如果因Z用Session或自定义存储? 式,您修改了后面要提到的媄响ViewState保存方式的方法SavePageStateToPersistenceMediumQ则q个Ҏ需要被 重写。默认的实现中ViewState是一UBase64格式~码Qƈ且被保存在页面的隐藏域中Q您可以使用q篇文章中提及的Ҏ修改ViewState 按以上两U方式保存。注意:q个Ҏq没有真正加载ViewState到页面或面控g中?/p>
² 当得到ViewState后,下一个方法LoadViewSateQ将以递归的方式恢复ViewState到页面及各个面控g或子控g中。这 个方法执行后Q每个控仉恢复到上一ơ的状态,但是用户提交的数据还没有应用到控件上Q因Z们不是ViewState的一部分。这个方法主要用于恢? 您在其他事g中动态生成的控g的|他们的值是您手动保存在ViewSate中,q且现在已经失效?/p>
² 下一个方法是ProcessPostDataQ这个方法也同样是回传的时候才会被执行Qƈ且不允许被重写,q个是页面基cȝU有Ҏ。这个方? 通过匚w控g的名U恢复相应的用户提交的控件的|到这一步意味着整个面都已l被完全恢复了。唯一要记住的是所有动态控件的创徏必须在这个方法之前。这 个方法也是记录后面的改变事g的方法?/p>
² 下一个方法是OnLoadҎQ通常q是用得最多的ҎQ因个方法是面生存期第一个恢复了所有值的地方。大多数代码Ҏ判断
IsPostBack来决定是否重新设|控件状态。您也可以在q个Ҏ中调用Validateq且查IsValid的倹{也可以在这个方法中创徏动态控
Ӟq且该控件的所有的Ҏ都会被执行以q上当前面的状态包括ViewSateQ不q不包括回传的倹{?br>l 事g处理
² 下一个方法还?
ProcessPostDataQ实际上是前一个方法的另一ơ调用,它仍然是只在回传的时候执行ƈ且由于是U有Ҏ不可以被重写。如果您是第一ơ看面
的运行轨q也怼觉得q个Ҏ有些多余。但实际上这个方法是必要的因为在OnLoad中创建的动态控件也需要他们回传的倹{Q何在q以后创建的控g可?
得到他们的ViewStateQ但是不能再得到他们的回传的|q且不会触发M值改变事?Change Event)?/p>
² 下一个方法,RaiseChangedEventsQ也是只在回传页面中执行Qƈ且也因ؓ是基cȝU有Ҏ所有不能被l承。在整个面生存? 中,是在q儿Ҏ之前的ProcessPostData记录的控件的值和提交的值是否不同来触发值改变事件。您也许需要调用Validate或者检? IsValid的倹{这里ƈ没有特别的说明多个值改变事件的执行先后序?/p>
² 下一个方法,RaisePostBackEventQ同h因ؓ是基cȝU有Ҏ不能被承,同样也是只在回传面中执行。除非用了 AutoPostBackQ不然这是实际提交表单事件执行的地方Q特别是按钮或者其实用javascript提交表单{。如果还没有被手动调用过q且? 用了验证控gQ那么Validate会被调用。注意IE中有个BUG有时会允许提交但却不触发M事g?/p>
² 下一个方法是OnPreRenderQ一般这是在客户端展现页面之前改变页面及其控件的最后一ơ机会。您也可以在q个Ҏ里面创徏动态控Ӟq? 且所有的Ҏ都会被执行以q上当前面的状态包括ViewSateQ但是私有方法将不会被执行,q意味着不会有回传的值ƈ且不会有事g触发。由于IE中的 BUGQ这是一个没有事件赶上PostBack的好地方?br>l 保存及显C?br>² 下一个方法是SaveViewStateQ不论是否是回传? 面,均会递归的执行以保存面及其所有控件的ViewState。ViewState基本上保存所有与定义在aspx中的原始g同的|不管是被代码q? 是用h改变。注意控件值是Ҏ他们在页面的控g树中的位|来保存的,所以如果动态控件后来加C错误的位|将会导致乱?/p>
² 下一个方法是SavePageStateToPersistenceMedium真正的保存页面的ViewSate。这个方法随? LoadPageStateFromPersistenceMediumg 一赯重写以便保存ViewState到Session或其它自定义数据Q而不是用隐藏域。这对于低带宽的用户来说是很有帮助的。ƈ且对于移动设备来_ Session是默认设|。下面这文章描qC使用以上两种方式保存ViewState的具体细节。注意在Asp.net中有个BugQAsp.net? 求必L交__viewstate字段Q即使是I的?/p>
² 下一个方法是RenderҎQ该Ҏ递归的创建ƈ发送相应控件的htmll浏览器。这个方法被一些页面模板方案重写以d一些通用的页面头? 脚而不使用服务器控Ӟ他们L有一些额外的东西。注意这儿的修改只能使用UHTMLQ因为控件在q儿已经被生成了。您可以? StringBuilderQStringWriterQHtmlTextWriter捕获相应的HTML输出?/p>
² 最后的Ҏ是OnUnloadQ这个方法会调用相应的DisposeҎ。这个方法提供机会以便清I面中用的非托资源,如关闭打开的文 件句柄,以前打开的数据库q接{。注意这个方法是在页面已l发送到客户端以后执行的Q所以它只有影响服务器对象,q且它不会显C在面的显Cq中。这? 是页面的生存期,对于每一ơ请求都是这么运行的?br>l 作者简??
?Q页面事件ȝ
Ҏ回传控g
ConstructorAlwaysAll
AddParsedSubObjectAlwaysAll
DeterminePostBackModeAlwaysPage
OnInitAlwaysAll
LoadPageStateFromPersistenceMediumPostBackPage
LoadViewStatePostBackAll
ProcessPostData1PostBackPage
OnLoadAlwaysAll
ProcessPostData2PostBackPage
RaiseChangedEventsPostBackPage
RaisePostBackEventPostBackPage
OnPreRenderAlwaysAll
SaveViewStateAlwaysAll
SavePageStateToPersistenceMediumAlwaysPage
RenderAlwaysAll
OnUnloadAlwaysAll