ColdFusion 9.0 Resources |
Using the Application Scope to improve COM performanceThe Java call to create a COM object instance can take substantial time. As a result, creating COM objects in ColdFusion can be substantially slower than in ColdFusion 5. For example, on some systems, creating a Microsoft Word application object could take over one second using ColdFusion, while on the same system, the overhead of creating the Word object could be about 200 milliseconds. Therefore, in ColdFusion, you can improve COM performance substantially if you can share a single COM object in the Application scope among all pages. Use this technique only if the following are true:
Because the object can be accessed from multiple pages and sessions simultaneously, also consider the following threading and locking issues:
Note: You can also improve the performance of some
COM objects by creating Java stubs, as described in Accessing Complex COM Objects using Java proxies. Using a Java stub
does not improve performance as much as sharing the COM object,
but the technique works with all COM objects. Also, generate Java
stubs to correctly access complex COM objects that do not properly
make all their features available through the COM IDispatcher interface.
Therefore, to get the greatest performance increase and prevent
possible problems, use both techniques.
Example 1: Using the FileSystem objectThe following example uses the Microsoft FileSystem Scripting object in the Application scope. This code creates a user-defined function that returns a structure that consists of the drive letters and free disk space for all hard drives on the system. <cfapplication name="comtest" clientmanagement="No" Sessionmanagement="yes"> <!--- Uncomment the following line if you must delete the object from the Application scope during debugging. Then restore the comments. This technique is faster than stopping and starting the ColdFusion server. ---> <!--- <cfset structdelete(Application, "fso")> ---> <!--- The getFixedDriveSpace user-defined function returns a structure with the drive letters as keys and the drive's free space as data for all fixed drives on a system. The function does not take any arguments ---> <cffunction name="getFixedDriveSpace" returnType="struct" output=True> <!--- If the FileSystemObject does not exist in the Application scope, create it. ---> <!--- For information on the use of initialization variables and locking in this code, see "Locking application variables efficiently" in Chapter 15, "Using Persistent Data and Locking" ---> <cfset fso_is_initialized = False> <cflock scope="application" type="readonly" timeout="120"> <cfset fso_is_initialized = StructKeyExists(Application, "fso")> </cflock> <cfif not fso_is_initialized > <cflock scope="Application" type="EXCLUSIVE" timeout="120"> <cfif NOT StructKeyExists(Application, "fso")> <cfobject type="COM" action="create" class="Scripting.FileSystemObject" name="Application.fso" server="\\localhost"> </cfif> </cflock> </cfif> <!--- Get the drives collection and loop through it to populate the structure. ---> <cfset drives=Application.fso.drives()> <cfset driveSpace=StructNew()> <cfloop collection="#drives#" item="curDrive"> <!--- A DriveType of 2 indicates a fixed disk ---> <cfif curDrive.DriveType IS 2> <!--- Use dynamic array notation with the drive letter for the struct key ---> <cfset driveSpace["#curDrive.DriveLetter#"]=curDrive.availablespace> </cfif> </cfloop> <cfreturn driveSpace> </cffunction> <!--- Test the function. Get the execution time for running the function ---> <cfset start = getTickCount()> <cfset DriveInfo=getFixedDriveSpace()> <h3>Getting fixed drive available space</h3> <cfoutput>Execution Time: #int(getTickCount()-start)# milliseconds</cfoutput><br><br> <cfdump label="Drive Free Space" var="#driveInfo#"> Example 2: Using the Microsoft Word application objectThe following example uses the Microsoft Word application COM object in the Application scope to convert a Word document to HTML. This example works with Word 2000 as written. To work with Word 97, change “Val(8)” to “Val(10)”. This example uses an Application scope lock to ensure that no other page interrupts creating the object. Once the Word object exists, the example uses a named lock to prevent simultaneous access to the file that is being converted. <cfapplication name="comtest" clientmanagement="No" Sessionmanagement="yes"> <!--- Uncomment the following line if you must delete the object from the Application scope ---> <!--- <cfset structdelete(Application, "MyWordObj")> ---> <!--- use the GetTickCount function to get a current time indicator, used for displaying the total processing time. ---> <cfset start = GetTickCount()> <!--- If necessary, create the Word.application object and place it in the Application scope ---> <cfset WordObj_is_initialized = False> <cflock scope="application" type="readonly" timeout=120> <cfset WordObj_is_initialized = StructKeyExists(application, "MyWordObj")> </cflock> <cfif not WordObj_is_initialized > <cflock scope="Application" type="exclusive" timeout="120"> <cfif not StructKeyExists(application, "MyWordObj")> <!--- First try to connect to an existing Word object ---> <cftry> <cfobject type="com" action="connect" class="Word.application" name="Application.MyWordobj" context="local"> <cfcatch> <!--- No object exists, create one ---> <cfobject type="com" action="Create" class="Word.application" name="Application.MyWordobj" context="local"> </cfcatch> </cftry> <cfset Application.mywordobj.visible = False> </cfif> </cflock> </cfif> <!--- Convert a Word document in temp.doc to an HTML file in temp.htm. ---> <!--- Because this example uses a fixed filename, multiple pages could try to use the file simultaneously. The lock ensures that all actions from reading the input file through closing the output file are a single "atomic" operation, and the next page cannot access the file until the current page completes all processing. Use a named lock instead of the Application scope lock to reduce lock contention. ---> <cflock name="WordObjLock" type="exclusive" timeout="120"> <cfset docs = application.mywordobj.documents()> <cfset docs.open("c:\CFusion\wwwroot\temp.doc")> <cfset converteddoc = application.mywordobj.activedocument> <!--- Val(8) works with Word 2000. Use Val(10) for Word 97 ---> <cfset converteddoc.saveas("c:\CFusion\wwwroot\temp.htm",val(8))> <cfset converteddoc.close()> </cflock> <cfoutput> Conversion of temp.htm Complete<br> Execution Time: #int(getTickCount()-start)# milliseconds<br> </cfoutput> |