PowerBuilder: Article

Web Load Test

Web Load Test

Do you ever wonder, after making a really cool JSP, PowerDynamo, or ASP page, just how much of a resource load will result? How many concurrent calls will max out the CPU on the servers? Wouldn't it be great if you could find out before the QA people start bashing on it? Wouldn't it be nice to avoid ordering a pizza and staying until the page is fixed?

If you're tired of unwanted surprises caused by pages that don't scale correctly, build a tool that allows you to avoid the problem. This article will show you how to build you own Web load testing tool.

I'll provide an overview of how you can build this type of application on your own. Go to www.powerobjects.com/jaguar/weLoad.htm and download it for free. You'll need to have the PB7 runtime DLLs on your machine.

The basic tools/objects needed are:

  • A window with some DataWindow controls to display results and collect parameters
  • An instance of Inet Object nv_inet
  • User Object inherited from Inter- netresult Object nv_netresult
  • User Object inherited from NonVisual- Object to move data to the window nv_return
Step 1: Collect Parameters
The application isn't huge; you only need one window for collecting parameters and displaying the results of the test. On a window place Single Line Edits for entering:
  • Number of threads ( sle_threads )
  • Number of loops ( sle_loop )
  • How often to log the information ( sle_log )
  • Which URL is going to get tested (sle_url )
Declare an instance of the nv_return object (also at the window level).

Step 2: The Inet Object
An inet object allows the application to make an HTTP request. Without the inet object this wouldn't be a Web application. Create a custom class user object that has an instance of an inet system object. Call it nv_inet. By creating a custom object you can add a few instance variables that will be used later in the application to transfer data back to the window for display.

Behind a button on your window loop for i = 1 to sle_threads and create an instance of nv_Inet object for each thread. The following code will do the job:

SharedObjectRegister(  "inet",
"inet"+string(i)  )
SharedObjectGet(  "inet"+string(i),
nv_inet  )
nv_inet.uf_SetReturn(  inv_return,
string(i),  sle_loop.text,
sle_log.text )
When you loop through these functions, SharedObjectRegister( ) spawns a thread belonging to the main threadgroup of your application, similar to grouping the threads in a Java application. The Shared ObjectGet( ) gets a pointer to a thread to initialize each thread. When the thread starts, it knows which URL to send a request to and how often to log data back to the application. The uf_SetReturn( ) provides each thread with the instructions it needs to execute.

Next, loop again and start each thread, making HTTP requests. Again use SharedObjectGet( ) for each thread and call the inet.GetURL( ) function. This is the weLoad application equivalent of calling the run( ) method in a Java thread.

Step 3: Making the Request
Important note: The scope required to get the results of the GetURL( ) function back to the DataWindow must be global or instance level.

The window instance of the nv_return object from Step 1 is crucial. By creating inv_return as an instance in the window object, anything we place into inv_return will have the scope required to get the data back to the DataWindows. You can see in Figure 1 that the threads are posted to the DataWindow asynchronously. This works because we initialize each thread with a pointer back to the inv_return, in the first loop of Step 2. The instructions give the thread the number of HTTP requests it should make and how often to log the results. As each thread hits the logging loop, it executes a function that posts results back to another function in the inv_return object.

How does each thread actually get the data? Threads create an instance of nv_netresult (Internetresults Object) for each HTTP request specified in sle_loop.text. The InternetData( ) function call of the inv_netresult is overridden. This allows the inv_netresult to process the data returned from the Inet.GetUrl( ithread, inv_netresult ), and place the data into the inv_return Object.

Step 4: Display the Data
When the results are logged ( sle_log.text ), the data is passed back from the threads via the posted function

call, inv_return, in the window object. The following line of code, from the inet object running in each thread, causes the return of the results:

inv_return.POST uf_Done( isz_id +
(len( isz_html ) ) )
The uf_Done( ) simply takes the tab delimited string sent to it and writes data out to the window with Data-window.ImportString( ). After the threads finish running, use Shared- ObjectUnRegister( "inet"+String(i) ) in a loop to clean up.

Congratulations! You have created a Web Load testing tool. You should end up with something resembling Figure 1.

Take It to 8
That was fun. You'll now use PowerBuilder 8 to migrate the application and add a new feature. Migrating applications to PowerBuilder 8 should be a snap. The Sybase design provides functions to pull existing applications into new storage areas specifically for applications.

There are two PowerBuilder 8 objects you'll need to get acquainted with workspace and target. See the Power-Builder 8 help files section on work-spaces and targets.

To migrate the application, create a new workspace, MyNewWork.pbw, with no associated targets. Select the existing application from the new menu on the target tab (see Figure 2).

PowerBuilder will recognize the previous version, remind you to back up all of the libraries, and give you the opportunity to specify/modify the library list to migrate.

When you are finished, your work space should resemble Figure 3.

Final Steps
Once you have successfully migrated the application to PowerBuilder8, add the Listing 1 code under the button that currently toggles between the graph and data views.

Next, paste an OLE Web browser control onto the window. Add the following code to the constructor event of the control. This will allow the new control to be sized as the DataWin- dows.

this.object.Resizable = true
return 1
In the resize event of the window, add the following code to correctly position and size everything.
dw_1.resize( newwidth - cb_1.x -
dw_1.x, newheight - dw_1.y - cb_1.x )
dw_2.resize( newwidth - cb_1.x -
dw_2.x, newheight - dw_2.y - cb_1.x )

ole_1.object.Width =
XUnitsToPixels!  )
ole_1.object.Height =
YUnitsToPixels!  )

sle_url.width = newwidth - cb_1.x -

It's said that seeing is believing. Now you can toggle between the data, graph, and a browser window to see the HTML of the page that you are load-testing. I'm sure you'll find many occasions to use this tool. You can even set up the pages to test transactional components that have to hit a database. If you want to go crazy, you can even get multiple threads hitting different pages of the same application. That'd be cool and maybe even get you home in time for dinner. Enjoy!

More Stories By Jerry Neppl

Jerry Neppl, previously CEO of a small liquidation company, has been working for PowerTeam, Inc., in Minneapolis, for the past year and a half, having fun and getting
paid to play everyday.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.