在线用户    站点地图 技术论坛 文档中心 站点导航 资源下载 语言参考 教程专题 站点统计 业务项目 使用帮助
您的位置
MSDN参考新加了CSS2参考,全中文,制作精良。245k下载。           新加了sxf_sxf推荐的"动态网页专家指导" 下载!          新加了lsg2002lsg推荐的"ASP.NET高级编程(PDF)" 下载!          新加了DHTML代码预览!!,功能强大哦!欢迎试用          新加了网友lincong为大家提供的SQL Server 2000 程序员指南,有点大,但同时也就说明内容全咯!           新加了网友ibra为大家提供的北大的JAVA课件,很适合初学者入门           新加了一个java的连接缓冲池代码示例           新加了人月神话电子版下载!软件工程巨著哦~~           更新了评分标准,引入了“专家分”概念,相信可以更好的激励大家的学习!详情请看“使用帮助”           新加了由网友GGG提供的“IIS超级管理手册”,值得一看哦!(虽然我没看过 :P )           新加了“英雄榜”,欢迎测试!           “无组件上传·从原理剖析到实践”已经全部完成,源码全部开放,有兴趣的朋友请到文档中心一探究竟。  您的位置  首页>热点专题 在同一窗口中打开页面中的链接 在新窗口中打开页面中的链接 将ASPCHINA设为首页 将ASPCHINA加入书签    
 LOGIN HERE
用户:
密码: 忘记密码
记住密码 用户注册 游客进入
 SEARCH
Add to Google
 STATISTICS
总访问量: **
今日统计: **
注册用户: 14708
总论题数: 30886
总回复数: 112477
技术文档数: 938
 SURVEY
查看所有投票题目

Component vs. Component Part II


Introduction


Welcome Back to my quest for superior component technology and the further development of my mock auction web application continue in this second half of my article. If you missed Part I you can read it here.

You Say "Server-Side Scriptlet;" I Say "Windows Script Component"


Both of these terms are the monikers for the same thing, but the former is now outdated. A Windows Script Component (WSC) is scripting language code that is converted into a COM interface, a process made easier by the Script Component Wizard. More information about all Microsoft scripting technologies and lots of downloads are available from Microsoft at http://msdn.microsoft.com/scripting

When you take code from raw ASP and convert it into a WSC you are adding one layer of abstraction that wasn't initially present -- the COM interface layer. The ASP functions you wish to convert will be wrapped with methods and properties that are exposed to any client that can create an instance of a COM object. This includes an ASP page or even a Windows Scripting Host (WSH)script. If you know your WSC is going to be used in the ASP environment, you can indicate this when you run the Script Component Wizard. This will give you a component which has built-in access to the intrinsic ASP objects (Response, Request, ) Well, that was the idea at least. While perusing the newsgroup microsoft.public.scripting.scriptlets I found much talk of a major memory-leak problem in components that are marked by the wizard to work with ASP. The known workaround is to pass in references to the ASP objects you will need, instead of letting the wizard explicitly declare them for you. It's a very simple workaround, and so far it prevents the memory leak. Another workaround is to use the Scripting Engine to be released with Windows 2000 (still in beta at the time of publication). There is a major drawback to using the intrinsic ASP objects inside a WSC. When you do this, you eliminate the possibility of being able to reuse your component in a non-ASP environment. And the main benefit of the component is, in fact, reusability and encapsulation.

To .Write() or not to .Write()


In part I, there were two ASP pages each built to handle specific tasks. There was also a static search.htm page. Each of the two ASP pages made use of shared functions that were made available by included files. How does all of this translate to the world of scripting components? My original thought was that I would combine all of my ASP page code into the component. This meant my component code would do all the response.write() calls and my calling ASP page would be extremely small. I was able to accomplish this, but some initial load testing opened my eyes to the fact that this was not a good idea. As you will see later, a Windows Scripting Component offer no performance improvement over ASP pages with Includes. I began this project with the misperception that WSC code was compiled to a lower level than regular ASP pages, and therefore was faster. In fact the WSC architecture can even be slower, depending on the situation. The benefit of the WSC lies in the encapsulation, object-orientation, and potential for reuse. It is definitely not performance. Letting ASP do what it does best by leaving all the HTML, etc., in the calling page is a superior architecture performancewise when compared to WSCs. The component's job should be getting data and performing business logic. With special care you can avoid using the intrinsic ASP objects inside your WSC and thereby create reusable components that don't lock you into the ASP environment.

Figure 1 displays the final code architecture from part I that is now converted to a Windows Scripting Component.

Figure 1


Example 1 shows the source code for ItemScripting.asp. This page is a converted version of Item.asp from part I of this article. The general flow is to first verify that the necessary data is present in the request, fire off the component to get the data, then begin formatting the output HTML. @ENABLESESSIONSTATE=False is used to turn off the overhead of tracking a user's session cookies. Like eBay, this application is totally stateless so there is no need for the Session object.

Example 1
<%@ENABLESESSIONSTATE=False%>
<% Option Explicit %>

<!--#include virtual="/Include/helper.asp"-->

<% 
'On Error Resume Next 
Response.Expires = 0
Response.Buffer = True

Dim strAuctionSeq
Dim oMyWSC, oRS
		
strAuctionSeq = Request.QueryString("AuctionSeq")

If strAuctionSeq = "" Then
Response.End 

Else
	Set oMyWSC = Server.CreateObject("myAuctions.WSC")
	oMyWSC.fetchAuctionDetail oRS, strAuctionSeq 
	If IsEmpty(oRS) Then
	Response.Redirect("error.asp?num="&Err.number&"&_
dsc="&Err.description&"&src="&Err.source&"&_
ctx="&Err.helpcontext&"&hfl="&Err.helpfile )
	ElseIf oRS.EOF and oRS.BOF Then
		Response.Redirect("noitem.asp?AuctionSeq=" & _
		    strAuctionSeq)
	End If
	Set oMyWSC = Nothing
End If
%>

<html>
<head>
<title>myAuctions Item <%=strAuctionSeq%>
(Ends <%=oRS("end_dt")%>) - <%=oRS("title")%>
</title>
<link REL="STYLESHEET" TYPE="text/css" 
HREF="/Styles/myAuctions.css">
<script>
Continue building HTML for Auction Item Detail
As you will see from the testing results, over time the scripting component does not execute any faster than the raw ASP. In fact it is slower. Why? Well, here is what I found after many testing iterations and several E-mail exchanges. Code that is inside a scripting component is still interpreted VBScript, just like an ASP page. The code is not compiled to a lower level than a regular ASP page. The first time the component is instantiated by a client, the scripting engine compiles the WSC source file and loads the image of this compilation into memory. The same thing happens to an ASP page and its Includes. In the end, it is the exact same code. There is no reason for the WSC-compiled code to Execute any faster! Disagree?

You might have read that a WSC application is faster than ASP with Includes because the WSC source file only has to be compiled once, while the code in an included ASP file has to be recompiled once for each page that includes it. This statement is also true under certain circumstances. Here's an illustration to help clarify this.

Figure 2


Let's start on the left side of Figure 2 with the ASP pages that are including the same file. When page 1 is requested the first time, it and the included file are combined, compiled, and put into memory, where they remain for the foreseeable future. When page 2 is hit, the same thing happens. The included file is recompiled for every page that includes it. Now, on the right side we have the WSC model. The first time any page is hit that creates an instance of our WSC, the Scripting Engine loads the source from disk, compiles it, and puts it into RAM. From then on, all the pages that use it share access to the same object, already compiled in memory.

If you construct a test where each of the different models have all 5 pages hit one time only, the WSC will come out on top. However, 5 hits and 5 hits only is not a realistic application load scenario. If you let the load tester repeat the 5 hits for a short duration, the plain ASP pages vault ahead of the WSC model in throughput and transactions per second. The extra payload brought on by creating and destroying an instance of the component on each page request and the inherent calls to IDispatch create more processor utilization and slower performance overall.

In my auction application it does not make sense to keep the object references around beyond the scope of a single page. If your user base was small and your memory plenty, you would be able to increase the performance of the WSC architecture by keeping your objects in session scope, or something similar. As with most issues in software development, there is no clear-cut solution.

From all of this we can confidently conclude one thing. The WSC architecture uses less RAM. If your application has thousands of ASP pages and many Includes, moving to WSC may help you. RAM usage is the only performance area where WSC beats regular ASP pages with Includes. However, I am not saying to avoid Windows Scripting Components in all situations.

Why Then?


At this point you might be asking, I like raw ASP, why would I want to convert a perfectly good raw ASP application into a Windows Scripting Component? Because if your scripting components do not use the intrinsic ASP objects, they can be reused by any other programming language that supports COM. We are talking real code reuse here! This doesn't seem like a tremendous benefit unless you have worked on an application that had various client interfaces. For example, a WSC serving a Web application could also serve as the data-access tier for a front end built in any other language running on a local PC, instead of a Web server.

There are still some additional good things about the Windows Scripting Component architecture to talk about as well! If you know you are eventually going to move to a compiled C++ or Visual Basic DLL, then the WSC can be used as an intermediary testing and staging architecture. You can later move to the compiled and linked language of your choice with stable, tested code. During development and debugging, Windows Scripting Components have an important advantage over compiled and linked DLL components built with C++, Visual Basic, or J++. You don't have to stop and start the Web services if you want to make a change to the code, and you can still debug the source code directly. This is a benefit that is easy to appreciate if you have ever debugged a DLL component written in a compiled and linked language. These kinds of components are loaded into the memory space of your IIS application, where they remain locked by the operating system until the both IIS services are completely stopped. This is an annoying downside of Active Server DLLs as you know, if you have ever had to debug one. When developing a Windows Scripting Component you can make a source code change in Interdev, hit the URL again with a browser, and see the results immediately. You can also step into server-side code inside the WSC source file if you have Visual Interdev server-side debugging configured. Of course, if you really are concerned about performance, you will have to bite the bullet and get into compiled Visual Basic or Visual C++ Active Server Components. Again, if you already have stable WSC code, moving it to one of the compiled and linked languages is a whole lot easier as I will demonstrate.

C++ How They Run


Most of the rest of this article covers porting the WSC code into an Active Server Component built with Visual C++ 6.0 and ATL. If you would like to see the performance testing results and are not interested in this, you may want to skip to the end now. I decided not to use any MFC in my component, opting for the minimal dependency, and fast scaleable architecture of pure ATL and WIN32. The final Release MinSize DLL turned out to be 142Kb. Porting the source from my scripting component to an Active Server Component developed with C++ was very natural. I needed the exact same interface methods and functions in my C++ project that already existed in my scripting component. All I had to do was create the interface and function architecture, paste in large sections of VBScript, and then work my way through the VBScript source to convert it to C++. The tough part was getting along without all of VBScript's inherent functions, such as Now(), and DateDiff(). I created a few hack versions of those functions that are full of logic bugs, but I got by.

MFC-ya


If you have relied a lot of Microsoft Foundation Classes (MFC), a class library for 32-bit Windows development, it takes a while to get used to the nature of pure ATL and automation types in C++. The Active Template Library (ATL) is a tool used to develop COM objects in C++. Not having CString at your disposal is a different kind of programming experience. However, once you learn the ins and outs of some of the automation helper classes in ATL, you begin to feel more powerful as you are unshackled from the bindings of MFC. _variant_t is a very useful automation helper class once you get used to the nature of a VARIANT. In fact using a VARIANT directly isn't so bad either.

The source code for the DLL port of this project is a great source for ADO and ASP object usage in a C++ project. Microsoft's ActiveX Data Objects (ADO) can be achieved through disconnected recordsets (see Part I of this article). Microsoft Data Access Components, the key technologies that enable Universal Data Access, include the ActiveX Data Objects, among others. There is a ton more helpful code examples than in the very limited IIS Software Development Kit's Simple and entermediate example C++ projects. It is not necessary for you to exclude MFC support from your ATL project, but I've found that MFC doesn't make automation types any easier so I leave it out when I can.

One important part of any successful ATL-based Active Server Component project is to support ISupportErrorInfo and to code heavily for exceptions. The code in my component does not do any of this. This is critical for real production code. You will not be able to get extended error information from ASP when an error happens, if you don't handle exceptions gracefully.

Should I Stop or Should I Start Now?


There is one complicated factor about developing an Active Server Component with a compiled language like Visual Basic or Visual C++ . Each time you want to make a change to the code and rebuild your DLL, you must start and stop the Web services. This is an enormous burden, even with a few helpful little tools that I wrote. You can use Start|Run commands to control the services, but it's rather clumsy. 揘ET STOP IISADMIN (which also stops W3SVC) stops all IIS-related services when you want rebuild your DLL. Then 揘ET START IISADMIN followed by 揘ET START W3SVC will get IIS ready to handle requests again. This is the second slowest way to do it besides using the Services Control Panel applet, but it is the only other way to do it!

You won't have any luck trying to use IIS Console Manager Stop and Start buttons. Those do not release the lock on your DLL. To alleviate some of this hassle, I created a short Windows Scripting Host script that would do these tasks for me, depending on either a STOP or START passed in the command line. After I added a shortcut for each to my IE 5 Quick Launch bar, it became trivial to stop and start IIS. It is still a production killer, but more bearable. The source for the Windows Scripting Host (WSH) program and the shortcuts are included in the source download. Adding these items as buttons on a toolbar of Visual Studio would also be a good way to handle this. Microsoft should develop a debugging version of IIS that eliminates this hassle and allows for easier debugging of live C++, Java, etc., DLLs in an IIS application.

In my ATL component I handled the architecture of the code quite differently from the previous two. I broke the rule of reusability and decided to go with the all-encompassing component model. Everything, including all of the HTML output, is inside the DLL. I knew that changing nothing, but adding the Idispatch layer, slowed things down. I wanted to see if the lower-level C++ code doing all the work would be faster than interpreted ASP. All signs point to Yes! While it does not blow the doors off ASP, it is faster. My DLL only does simple database access through ADO and some Response.Write calls. Thus it does not showcase the true speed advantage of a C++ component. A number-crunching application would probably do an even better job of that.

After my three components were built and working normally, it was time to put them to the test.

Loading Zone


RadView's WebLoad 3.5 was easy to install. It was hard to figure out the quirky interface but it did the job well. It uses JavaScript to create testing 揳gendas and also exports the testing data directly to Microsoft Excel. Its best feature is the ability to record your script by using a browser. You can download the spreadsheet files that contain all of the statistics from the test as part of the source download for Part II of this article. The graphs below display two of the most important statistics. Throughput is in Kbytes per second and transactions per second. You should not pay too much attention to how high (or low) the numbers are, because my lab equipment was less than ideal.* Instead look at the differences among architectures.

Figure 3*

*My testing machine was a PII 350, with 128MB RAM, NT4 SP5, SQL 7 and IIS 4 on the same box. WebLoad ran from a Pentium workstation connected by a 5- port hub.
Here you can see the differences in performance are measurable but small. The bottleneck in this test was searching the database, not creating the pages, a task not made easier by the fact I had IIS and SQL 7.0 running on my test server. The ATL component nudges out ASP in both categories. These figures resulted from setting WebLoad to continuously request 5 different searches for 10 minutes.

A greater difference in performance is visible in figure 4, the Auction Item lookup test.

Figure 4

Here the numbers are better because the database was not getting used heavily. The primary bottleneck is the processing of the page code by IIS. These figures resulted from setting WebLoad to continuously request 5 random auction sequence numbers for 10 minutes. While the ATL component is fastest, it had a downside. The processor utilization was much higher for it than the ASP pages with Includes. The same thing happened for the WSC, too. I believe this is due to the additional IDispatch layer overhead.

Conclusion


C++ / ATL is where the performance is at, but at the cost of increased time to develop and debug. A good way to overcome those negatives is to solidify your code as a WSC first. Good old ASP pages with well-written libraries of reusable functions are not looking so bad either. A clear next step in the progression would be to throw a DLL built with Visual Basic, or an ISAPI Extension DLL, into the fray of our testing. Incorporating Microsoft Transaction Server, or keeping the object instances in Session or Application scope, may also effect results dramatically.

If there is enough interest, I may take these tasks up in a follow-up article. Another good idea would be to test a more robust component versus a very large included library of ASP. If you are struggling trying to decide which architecture is best for your application, do some simple proof-of-concept testing yourself. Some quick and dirty load testing will get you familiar with the details of each method and will help you make a sound decision based on your own facts.

One thing is for sure, developing components based on any of the architectures that aren't locked into the IIS environment is the most desirable strategy. Take a look at the live application. The source code download for Part II of the article includes all the WSC source, the C++ ATL component, and the performance data from WebLoad in Microsoft Excel spreadsheets.

Download


The database scripts, BCP code, and ASP application source are available for download here.
ftp://ftp.15Seconds.com/991104.zip

PART I                Back To Top


您的位置
  (c)2000-2019 Yup Studio, all rights reserved.  
0