LoadRunner Script Runtime Settings

October 15th, 2006

When running a training or mentoring session, people often ask what runtime settings they should use; as if there is a magical list of settings that will always be correct for any testing situation. Obviously you select runtime settings that are appropriate for what you are trying to achieve with your test, but the funny thing is that there are actually a small list of settings that are usually appropriate for most situations. Read on…

General: Run Logic

Whenever I am using a vuser type that allows multiple actions in a single script, I will create a separate action for each business process and put appropriate percentage weightings on each action. It is very unusual to have to do anything more complicated than this. I don’t usually use the “sequential” option or create blocks unless I need to have fractional percentage weightings for a business process – percentages must be integer values, so to run a business process 0.1% of the time you could create a block that runs 1% of the time, and put an action in the block that runs 10% of the time.

It’s also rare to set a script in a scenario to run for a specified number of iterations (mostly done by time or set to run indefinitely). Generally “number of iterations” is only used when running the script in VuGen.

General: Pacing

  • “As soon as the previous iteration ends” is used when running in VuGen or when loading/verifying data. Do not use this for load testing
  • I have never seen the point of the “After the previous iteration ends” option. Why would you want to run an unknown number of transactions per hour against the system?
  • Don’t use the “At fixed intervals”. If something causes your users to become “in step”, they will tend to stay that way and continue to all hit the server at the same time.
  • “At random intervals” is definitely the way to go. Obviously for your users to create a certain number of orders per hour the iteration time must average to 3600/num iterations in an hour. Do not make the lower boundary value any bigger than the maximum time it takes to complete the business process, or you will end up creating less transactions per hour than you intend to.

General: Log

  • Logging creates additional overhead on your load generators, and can create huge log files.
  • I log absolutely everything when debugging in VuGen.
  • When running the script as part of a scenario, I leave extended logging on but change the logging to “Send messages only when an error occurs”. This gives a little more information than turning logging off entirely, and won’t create any additional overhead while everything is running smoothly (and if the system is not running smoothly you are going to need to stop the test and investigate anyway).

General: Think Time

  • Just like the pacing setting, I think that it is a good idea to put some randomness in your think times.
  • I use a random percentage of 50-150% of recorded think times.
  • Use “Ignore think time” if you are debugging in VuGen or if you are loading/verifying data.

General: Additional Attributes

  • This option is ignored by most people. It is used to create a parameter with a given value without having to edit the script (as runtime settings can be overridden in the Controller).
  • In the screenshot I have created a parameter of ServerName with the address of the test envioronment. If you were testing in more than one test environment at a time, this would make save some time.

General: Miscellaneous

  • Continue on error is generally only going to be used if you have written code to do something when you encounter an error. Usually the default behaviour of ending the current iteration and then starting the next one is sufficient). I don’t advise anyone to try to write a script that handles errors in the same way as a real user because it will create a lot of additional work for very little benefit, but doing something simple like writing some useful information to the logs and then calling lr_exit(LR_EXIT_ACTION_AND_CONTINUE , LR_FAIL) can be useful.
  • “Fail open transactions on lr_error_message” should always be ticked. If you are raising an error, you should fail the transaction step that you are performing.
  • “Generate snapshot on error” is useful. If it is a web script, any error messages should be added to your content check rules.
  • Run your virtual user as a thread unless you have code that is not threadsafe or there is some other reason to run your virtual users as a process. The overall memory footprint on your load generators will be higher if you run as a process.
  • I never use the “Define each action as a transaction” option. If I want a transaction in my script I will add it myself with lr_start_transaction.
  • I never use “Define each step as a transaction” either. If it is a web script, I can use the transaction breakdown graph to get this information, otherwise I will add the transactions myself.

Network: Speed Simulation

  • Not all vuser types have this option available.
  • Most of the time my virtual users will use the maximum bandwidth.
  • If I want to emulate users with bandwidth constraints, I will do this in a separate scenario.
  • Google calculator is handy to calculate bitrates if your bitrate is not available from the drop-down list e.g./ “256 Kbps in bps

All of the following settings only apply to web-based scripts. Each vuser type will have its own runtime setting options. It is important to know what they mean and how they will influence your test results before running any tests that you plan to report on.

Browser: Browser Emulation

  • Some people get confused by the User-Agent (browser to be emulated) setting. If 90% of your users use Internet Explorer 6.0 and the rest use Firefox 1.5, you don’t have to change the runtime settings for your users to match this. All it changes is the string that is sent in the “User-Agent” field of your HTTP requests. This is completely pointless unless your application has been written to serve different content to different browsers based on the User-Agent field.
  • TODO

Internet Protocol: Proxy

  • Generally people won’t be using your web applications through your proxy server, so it shouldn’t be part of your test either.
  • If you start getting errors that are due a proxy server rather than the system under test, it will just confuse the people who have to fix the problem.
  • A proxy server will also make IP-based load balancing ineffective.
  • If it’s an intranet application and everyone will be using the application through the company’s proxy, then the proxy server should be explicity declared to be in scope for your load test. You should make sure that you have an identical proxy server for your test environment, or that you have permission to be generating load on a piece of Production infrastructure.

Internet Protocol: Preferences

  • TODO

Internet Protocol: Preverences - Options

  • These settings are default values specified by Mercury, rather than being inherited from the web browser that is installed on your workstation. Generally you will not need to change them, but be aware that they are here.

Internet Protocol: Download Filters

  • Download filters are a quick way of preventing your scripts from downloading content from certain URLs or hosts/domains.
  • I generally use this feature when the web application in the test environment contains third-party images used for tracking website usage (e.g. images from Webtrends or Red Sheriff etc).
  • I think it is better to specify which hosts your script is allowed connect to, rather than which hosts your script can’t connect to (because it’s easy to miss one accidentally, or the application may change and refer to a new third-party domain).
  • Use web_add_auto_filter if you want to specify this in your script rather than your runtime settings.

Internet Protocol: ContentCheck

  • I have talked about Content Check rules before; I think that if you aren’t using them already, then you are not getting the most out of the LoadRunner feature-set.

LoadRunner Vuser Types

October 8th, 2006

As of LoadRunner 8.1, Feature Pack 3, the following Vuser types are available (note that descriptions are provided by Mercury).

LoadRunner Vuser types - Popular Protocols

Application Deployment Solutions

  • Citrix_ICA
    Represent the Citrix ICA protocol communication between the Citrix client and server as GUI events.

Client/Server

  • DB2 CLI
    The IBM Call Level SQL Interface to the DB2 family of databases.
  • Domain Name Resolution (DNS)
    A system which translates domain names into internet addresses.
  • Informix
    IBM’s Informix Database servers.
  • MS SQL Server
    Microsoft’s SQL Server using the Dblib interface.
  • ODBC
    Open Database Connectivity – a protocol providing a common interface for accessing databases.
  • Oracle (2-Tier)
    Oracle database using a standard client/server architecture.
  • Sybase CTlib
    A client/server architecture database called via the Ctlib interface.
  • Sybase DBlib
    A client/server architecture database called via the Dblib interface.
  • Windows Sockets
    The standard network programming interface for the Windows platform.

Custom

  • C Vuser
    A generic virtual user which uses the standard C library.
  • Java Vuser
    Java programming language with protocol level support.
  • Javascript Vuser
    A scripting language used to develop Internet applications.
  • VB Script Vuser
    Visual Basic Scripting Edition language – used for programming documents displayed in Web browsers.
  • VB Vuser
    Vuser scripts written in Visual Basic language.
  • VBNet Vuser
    Vuser scripts written in Visual Basic language.

LoadRunner Vuser types - Custom

Distributed Components

  • COM/DCOM
    Microsoft’s Distributed Component Object Model (COM/DCOM) for distributed computing.
  • Corba-Java
    Java scripts which use CORBA architecture giving applications the ability to work together over networks.
  • Rmi-Java
    Remote Method Invocation – a technology providing remote communications between programs written in the Java programming language.

E-Business

  • Action Message Format (AMF)
    A Macromedia proprietry protocol that allows Flash Remoting binary data to be exchanged between a Flash application and an application server over HTTP.
  • File Transfer Protocol (FTP)
    File Transfer Protocol – a system which transfers files from one location to another over a network.
  • Listing Directory Service (LDAP)
    Record directory based authentication, listings, searches and related transactions.
  • Microsoft.NET
    Supports Microsoft ADO.NET.
  • Palm
    Palm Handheld computers.
  • Web (Click and Script)
    Emulation of the communication between a web browser and the web server at user-action level.
  • Web (HTTP/HTML)
    Emulation of communication between a browser and Web server.
  • Web Services
    Web Services – a software interface defined and described using XML.
  • Web/Winsocket Dual Protocol
    A dual protocol incorporating the Web and Winsocket Protocols.

LoadRunner Vuser types - E-Business

ERP/CRM

  • Oracle NCA
    Oracle 3-tier architecture database consisting of Java client, Web server and database.
  • Oracle Web Applications 11i
    In addition to Web HTTP/HTML features, supports the user action level API and JavaScript, with a high level of support for Oracle Web Applications 11i environment.
  • PeopleSoft Enterprise
    In addition to Web HTTP/HTML features, supports the user action level API and JavaScript, with a high level of support for PeopleSoft environment specifics..
  • PeopleSoft-Tuxedo
    An Enterprise Resource Planning system based on the Tuxedo Transaction Processing Monitor, including automatic correlation.
  • SAP – Web
    Similar to Web HTTP/HTML, but equipped to work in conjunction with SAP.
  • SAPGUI
    SAPGUI protocol for SAP Front End, versions 6.20 and higher.
  • SAPGUI/SAP-Web Dual Protocol
    SAPGUI and SAP-Web dual protocol for SAP Front End, versions 6.20 and higher.
  • Siebel – DB2 CLI
    A Customer Relationship Management Application based on a DB2 database.
  • Siebel – MSSQL
    A Customer Relationship Management Application based on the ODBC database API.
  • Siebel – Oracle
    A Customer Relationship Management Application based on an Oracle database.
  • Siebel – Web
    Similar to Web HTTP/HTML, but equipped to work in conjunction with Siebel, a Customer Relationship Management Application.

LoadRunner Vuser types - ERP/CRM

Enterprise Java Beans

  • Enterprise Java Beans (EJB)
    Enterprise Java Beans – an architecture for the development and deployment of Java-server components.
  • Rmi-Java
    Remote Method Invocation – a technology providing remote communications between programs written in the Java programming language.

Legacy

  • Terminal Emulation (RTE)
    Emulation of users who submit input to, and receive output from, character-based applications.

Mailing Services

  • Internet Messaging (IMAP)
    Internet Message Application – a protocol which enables clients to read email from a mail server.
  • MS Exchange (MAPI)
    Messaging Application Programming Interface designed to allow applications to send and receive email messages.
  • Post Office Protocol (POP3)
    A protocol designed to allow single computers to retrieve email from a mail server.
  • Simple Mail Protocol (SMTP)
    Simple Mail Transfer Protocol – a system for distributing mail to a particular machine.

Middleware

  • Jacada
    A gateway server providing clients with a Java user interface to mainframe applications.
  • Tuxedo 6
    Tuxedo 6.x Transaction Processing Monitors.
  • Tuxedo 7
    Tuxedo 7.x Transaction Processing Monitors.

Streaming

  • Media Player (MMS)
    Streaming data from a media server using Microsoft’s MMS protocol.
  • Real
    A protocol used to transfer streaming data from a media server.

Wireless

  • i-mode
    NTT DoCoMo’s technology for accessing the Internet on a mobile phone system.
  • Multimedia Messaging Service (MMS)
    Multimedia Messaging Service – used for sending MMS messages between mobile devices.
  • VoiceXML
    A standard for voice-based communication between applications.
  • WAP
    Wireless Application Protocol – used for Web-based, wireless communication between mobile devices and content providers.

SAP Cheat Sheet for Performance Testers

October 1st, 2006

Performance testers must switch between different technology platforms almost every time they join a new project. Here are a few things you should know so you don’t look like a complete n00b on your first SAP project.

Transactions and Sessions

Unless a restriction has been put in place, users may create multiple sessions from a single workstation. Using the menu, this can be done through System > Create Session or by left-clicking on the top right of the SAP client window and selecting the Create Session option.

Create new session

This menu is also the only place a transaction may be stopped if a dialog step is taking a long time to complete. Ending a transaction that has stopped responding by using Windows Task Manager to kill your SAP client is a bad solution, and I have seen it leave zombie processes running in the system.

Most of your navigation probably won’t be done using the menu tree, but by entering a transaction code in the command field.

SAP client command field

In the above screenshot I am jumping directly to the Data Browser, which has a transaction code of SE16. There are several other things we can do in the command field:

  • /x is a shortcut for exiting the system
  • A new session can be opened with /o[Transaction Code]. E.g. “/oSE16″ would open another session and start the Data Browser
  • If you are already in a transaction and want to jump to another, you would use /n[TransactionCode]

Be aware of where you invoke a transaction in your LoadRunner script. If you are restarting a transaction every time you iterate through the Action section of your script, you may be creating an unrealistic usage pattern (unless your users really will restart the transaction every time they use it).

Extracting Data

If you need to automate anything within SAP, like small-scale data loads or data extractions through the GUI, it is easier to use QuickTest Pro (if you are licensed) rather than CATT/eCATT scripts, which are a big pain in the butt.

Regular cut and paste does not work for all of the SAPGUI widgets. Where this is the case, you will have to use Ctl-y to select text before you can copy the text to the clipboard.

If a data grid does not have an export button to allow you to export data to a local file in Excel format, you have another option. Choose System > List > Save > Local File, and choose your preferred file format.

Save to local file

If you have access to the Data Browser (SE16), you can extract data from the database tables directly. Because SAP want their software to be independent of the underlying database, they discourage the use of SQL, so you must query the table using their forms.

SAP data browser (SE16)

Extracting data from tables rapidly becomes painful if your data spans multiple tables, because you can’t do a join. The (hacky) solution to this is to either extract both tables to Excel and join there (small data sets only), or right click in the field in the second table that is the key and choose multiple selection from the context menu. This will allow you to run a query on the table to match all the records that have your key value.

SAP data browser multiple selection

Finding the correct database table can be tricky as most tables and fields have cryptic names (very short German abbreviations). The field and table behind an edit field in your application can be found by placing the cursor in the edit field and pressing F1 (help).

SAP performance assistant

Click on the icon with Technical Information icon (with the hammer and spanner), and the technical details behind the field will be displayed.

Technical information

If you are lucky, you will be given a table and field name, otherwise you will be given a Struct. This is a data structure in the ABAP code that may have pulled data from multiple tables (or wherever). You will also be able to see the field in the struct and the underlying field (data element) in the database. Double click on the data element and you will be taken to a data dictionary view. Press the Where-Used List button to see a list of all the tables that have this field. Double click on the field name under the correct table and you will be taken to the data dictionary view of the table. Confirm you have the correct table and then jump back to SE16 to construct your query.

End-user Performance

I’ve talked about this before, but I think that the transaction timer in the SAP client is quite a neat feature.

SAP client response timer

It measures how long each dialog step takes, so if you press a button and you have wait for a response from the server, the timer will run until the response is received. Note that if multiple dialog steps are executed when you press the button, the timer will measure each individually (causing the timer value to update with a new value for each dialog step), and you will finish with only the last value.

Note from the screenshot, you can also see the transaction code for the current transaction in this menu.

LoadRunner Scripting

SAPGUI is one of the easiest vuser types you will ever use. Read all the LoadRunner documentation and you shouldn’t have many problems. Be aware that you can only run a limited number of virtual users on each generator due to GDI resource limitations. The work-around for this is to open up multiple Terminal Services sessions, each of which has its own allocation of GDI objects. You may need to run fewer virtual users in each TSC session if your application is graphically rich.

Further Reading

  • Make sure to read enough that you will understand the SAP architecture for your project, also any tuning guides are useful
  • Read the relevant sections in the LoadRunner manual
  • Search the Mercury Support Knowledge Base for SAP-related tips and tricks. Read Problem ID: 11907 – How-to and troubleshooting guide for SAP Vuser
  • Read the slides from my Mercury World Australia presentation on Mercury Diagnostics for SAP
  • Finally, I plan to make a list of SAP transaction codes that are useful to performance testers, so check back soon

Network Sociability Testing

September 24th, 2006

If the application that you are performance testing will be operating over a WAN, it is really important to test whether the reduced bandwidth and higher latency of the network link will increase transaction response times to an unacceptable level.

If you are being thorough, you should also run some tests to determine whether your response times will be impacted by other network traffic on the WAN (and vice versa).

Network cable, top view (credit: Quark67, Wikimedia Commons)

Let the following anecdotes about testing two different applications serve as examples:

The first application was to be used by staff who would be interacting directly with customers. There would be up to 10 concurrent users per site, each spending the majority of their time using this application. In addition to the network traffic from the application, there would be back-office traffic like web browsing, email, and software packages being deployed to workstations. The Project had some concerns about the impact of this traffic (particularly package deployment) on end-user response times for this business-critical application.

A leased line with the same specifications as the (future) Production WAN links was provisioned for the test environment. A LoadRunner agent was set up at the end of the WAN link to generate traffic equivalent to 10 concurrent users. The background network traffic was generated with NetIQ’s Chariot tool.

Chariot sends packets (with a typical packet size for each type of traffic to be emulated) at specified volumes between user-defined ports on each end-point, which sit at either end of the WAN link.

The network team spent several days determining the profile of the background traffic and creating a number of traffic scenarios in Chariot. The different traffic scenarios were run at the same time as a worst-case profile of heavy application usage. The response times from these scenarios were compared with end-user performance from a scenario with no background traffic (and, obviously, against the performance requirements).

Network cable, bottom view (credit: Quark67, Wikimedia Commons)

The second application was to by used by staff working in a warehouse. There would only be 1 or 2 concurrent users per site, and the traffic would be low volume – mainly related to printing picking slips and labels. This was tested using one of the warehouse WAN links; using real Production infrastructure meant that the tests had to be run ridiculously early in the morning to ensure that they would not interfere with normal Business activities.

The testing was nowhere near as sophisticated as the first example. A user was located at the warehouse with a stopwatch to measure response times. It was not necessary to use LoadRunner as there would only be a small number of users at the site, and LoadRunner would not be able to measure the time it took for output to appear at the printers.

A baseline with no additional network traffic was run. Multiple samples were taken for each business process to provide a meaningful average response time that could be reported on.

To emulate network activity, I ran a batch file that repeatedly copied a zipped file across the WAN (the file was zipped in case any network components were trying to compress traffic). The network team, who were monitoring the link, reported that the link was at 40% utilisation. As file transfers had a lower QoS priority than application or printer traffic, no significant change in response time was expected.

The business processes were re-run, and results were recorded. As expected, there was no statistically significant difference in response times.

Running a second instance of my batch file increased the network link utilisation to 90%. This time response times were higher, but still within requirements.

Just for the sake of completeness, here is the batch file:

:: Copy file.zip from shared drive
:: to the local D:\TEMP directory.
:: Loop forever (or until Ctl-C).
:: Rename the copied file as file<iteration>.zip.
@echo off
SET /A i=1
:copy
echo copying file%i%...
copy /Y \\dws0368\Temp\file.zip D:\TEMP\file%i%.zip
SET /A i=%i+1
goto copy

As with any sociability test, you can put in a level of effort that is likely to reduce the risk of unexpected behaviour in Production to an appropriate level. You could spend a lot of time making your usage profile “perfect” and testing every scenario, but it saves valuable time to concentrate on a probable-worst-case and simplify you usage profile as much as is practical.

Of the two examples, one took a couple of hours to prepare and execute, the other took a few days and involved significant work from other groups. While I would prefer to do this testing the first way if possible, the quick-and-dirty second way is an example of “good enough” testing (and, with historical graphs of network usage, is almost as defensible as the first example).

Mercury Virtual Table Server (VTS 2)

September 17th, 2006

The Virtual Table Server (VTS) is an in-memory database that can be used to share data between virtual users. I have found this useful when I need my VUsers to pass data to each other; it’s certainly a much neater solution than writing to a file and having each VUser check the value in the file on every iteration.

Here is what the documentation has to say about it…

VTS Virtual Table Server (version 2.10)

Virtual Table Server (VTS) first edition, introduced the capability for LoadRunner virtual users, WinRunner and XRunner, to communicate in real time. Data extraction and communication was simplified but limited to column/queue level operations. The new Virtual Table Server II provides a higher degree of data manipulation and 5-10 times better performance. From row level queries, retrievals, updates, insertions, unqueue entries, to database access, VTS II provides the functionality and ease for enhanced inter-process, inter-virtual user communication

Mercury Virtual Table Server (VTS)

One of the limitations of LoadRunner is that a parameter file cannot be shared between different scripts, or between instances of the same script running on different load generators. VTS is an easy way to maintain a single data pool. This is less of a problem if you are using Performance Center, as it is smart enough to allow the same script to run on multiple generators and still maintain the “Select next row: unique” property.

Another limitation that the VTS solves is the ability to maintain information about which data values have been used *between* runs. If you have a script that consumes data (maybe it deletes records), data values can only be used once. This means that every time you run the script, you have to update the data file. Using VTS, you can mark the data as “dirty”, so the next time the script is run, it will use a different value.

Virtual Table Server (version 2) can be downloaded from the Mercury Support website. Note that even though the software is provided by Mercury, it is not officially supported.

Installation is simple, and the server can be configured to run on any port. The API and examples provided with the software work with C-based scripts. A Java API is also provided. JavaScript and VBScript vuser types are not supported.

The API is simple, but unfortunately does not allow you to write SQL queries; instead you must use the functions provided, like lrvtc_retrieve_row() and lrvtc_query_row(). Finally, the VTS can import from and export to a regular database (anything with an ODBC driver), or a text file.

This is a useful tool for anyone who uses LoadRunner to be aware of.

Discovering your website usage profile with LogParser

September 10th, 2006

It’s always nice to base your load test on real-world usage patterns rather than someone’s “best guess”. If the system is used internally, Business Analysts are usually quite good at providing this information, but if the system is used by external users (like most high-traffic web applications), then they can typically only tell you “big picture” information; e.g. they know how many orders are created, but not how many searches are made per hour.

Basic web log analysis tools provide low-level technical detail that isn’t very useful – hits per hour. To be useful for load testing, we need to translate the data in the logs into end-user business processes and their respective volumes during a peak hour.

Typically this analysis effort is worthwhile when:

  • You are testing a web application that is a replacement for an existing web application, and can therefore be assumed to have a similar usage profile.
  • Your web application has gone live, but you want to validate the “best guess” usage profile that was used for load testing against actual usage patterns. If you tested with less load or used a significantly different usage profile, you might want to run some more tests to make sure that you won’t see problems in the future. You will also be able to use this new profile for future regression tests.

An e-commerce website may have a number of common functions – register, login, update details, search for product, browse catalogue, add to basket, checkout, logout, etc. Using an analysis tool such as LogParser (which I have discussed before), we can map the page requests in the log file onto these functions.

If you are in a hurry to get started, the steps are as follows:

  1. Get a copy of the log files for a peak day.
  2. Extract the top page requests from the file.
  3. Determine which page requests map to which business processes.
  4. Query the log file for the relevant page request that identifies each business process. Pick the busiest hour.

Everyone else, read on…

Hopefully your system administrators are keeping the web server logs for at least a week. Log files will probably be split into a separate file for each day. Ask for the largest log file. Make sure you get the log files for the same day from each web server.

Run a LogParser query to extract all the URLs from the log and sort them by popularity. This gives a good overview of system usage. We can safely exclude any static content (images, stylesheets, JavaScript files) and any errors. The size of the output file can be substantially reduced by excluding pages with a small number of hits (we don’t care about any pages that are low-volume anyway).

SELECT
   COUNT(cs-uri-stem) as Hits,
   cs-uri-stem AS URL
FROM
   C:\TEMP\logs\ex060910_*.log
WHERE
   sc-status <> 404 AND
   EXTRACT_EXTENSION(cs-uri-stem) NOT LIKE 'jpg' AND
   EXTRACT_EXTENSION(cs-uri-stem) NOT LIKE 'gif' AND
   EXTRACT_EXTENSION(cs-uri-stem) NOT LIKE 'css' AND
   EXTRACT_EXTENSION(cs-uri-stem) NOT LIKE 'ico' AND
   EXTRACT_EXTENSION(cs-uri-stem) NOT LIKE 'js'
GROUP BY
   URL
HAVING
   Hits >=5
ORDER BY
   Hits DESC

The overview will generally show that the majority of the requests to the web application are hitting a small number of pages (80/20 rule).

Next, record the key business processes (that you know of) with VuGen using URL mode. This is a simple way of creating a list of all the URLs that each business process covers. Try to pick a URL that uniquely identifies each business process. Take note of the following attributes that are included in the web server log files:

  • cs-uri-stem – usually the filename on the webserver, like “/search.php”
  • cs-uri-query – if the URL has any arguments that are passed in after the filename, these are included here; like “?query=foo&lang=en”
  • cs(Referer) – the complete URL of the previous page
  • cs-method – the HTTP method of the request, usually GET or POST.

Check that there aren’t any popular requests in your overview list that aren’t covered by the business processes that you have recorded.

Finally, write a query using the above information to count the number of times a given business process was run during your peak hour. E.g.

SELECT
  TO_LOCALTIME(QUANTIZE(TO_TIMESTAMP(date, time), 3600)) AS TimeStamp,
   COUNT(cs-uri-stem) as Hits
FROM
   C:\TEMP\logs\ex060910_*.log
WHERE
  cs-uri-stem = '/addToBasket.php' AND
  cs-uri-query LIKE 'item=%' AND
  cs-method = 'GET' AND
  cs(Referer) = 'https://www.store.com/display.php?item=%'
GROUP BY
   TimeStamp
ORDER BY
   TimeStamp

…which gives the following output (in CSV format). Note that the original timestamps were in UTC+0, which was converted to Australian Eastern Standard Time (UTC+10).

TimeStamp,Hits
2006-09-10 10:00:00,933
2006-09-10 11:00:00,935
2006-09-10 12:00:00,761
2006-09-10 13:00:00,655
2006-09-10 14:00:00,705
2006-09-10 15:00:00,680
2006-09-10 16:00:00,565
2006-09-10 17:00:00,231
2006-09-10 18:00:00,105
2006-09-10 19:00:00,66
2006-09-10 20:00:00,60
2006-09-10 21:00:00,65
2006-09-10 22:00:00,98
2006-09-10 23:00:00,36
2006-09-11 00:00:00,26
2006-09-11 01:00:00,15
2006-09-11 02:00:00,16
2006-09-11 03:00:00,17
2006-09-11 04:00:00,23
2006-09-11 05:00:00,24
2006-09-11 06:00:00,20
2006-09-11 07:00:00,43
2006-09-11 08:00:00,182
2006-09-11 09:00:00,398

From this, we can easily see that the peak hour for this business process is between 11 and 12, and we can feed the transaction volumes into the usage profile that will be used for load testing. Rinse and repeat for each business process.

Performance Testing Notepad

September 3rd, 2006

Performance testers sometimes get hung up on tool-based testing. Admittedly, most of the really interesting problems appear when there are more than a few concurrent users on a multi-user system, but it is important to verify that an application performs acceptably when it is not under load too.

Even if response times seem fine during functional testing, the functional test team may not have thought to look for the effect of large datasets on response times. It’s not just a case of “do we need to put an index on a table somewhere”, but sometimes response times increase exponentially instead of linearly as the dataset increases.

This is especially noticeable with poorly written batch jobs. The job might take 1 minute to process 1,000 records, but it does not necessarily follow that processing 100,000 records will take 100 minutes.

For an example of an application that seems to have implemented Shlemiel the painter’s algorithm, take the Replace function in Notepad. Performing a find-and-replace on a small file is very fast, but performance quickly degrades as the file gets larger.

Notepad find-and-replace

As you can see from the graph, the increase in response times is definitely not linear as the file size increases.

Notepad find-and-replace response times

Using an even larger file containing 10,000 lines, the operation completes in 28 minutes. Compare this to the response times for another text editor such as TextPad – all files up to 10,000 lines were processed in less than 1 second.

If you would like to experiment with this feature, text files of different sizes are available here (155kB zipped).

Scripting Exercise: A basic AJAX application

August 28th, 2006

A common question on the LoadRunner support forums is “I’ve got an application that uses this new thing called AJAX. Will LoadRunner work with my application?” …and the answer is “yes…but…”.

The “but” is a big one . An “AJAX” application can mean anything from a simple webpage that updates some fields with information from the server (without reloading the whole page), to a horribly complicated rich GUI interface created with JavaScript.

Of course LoadRunner is going to be able to handle anything that is sent over HTTP, but scripting might not be the usual simple Record-Correlate-Playback, and the chances of the new Click and Script vuser type working are much lower than with a standard web application.

As a quick introduction to AJAX I have prepared an exercise using the simplest AJAX application that I could find.

Google Suggest

Google Suggest is just like Google’s regular search interface, except that every time you type a letter in the search field, a request is made to the server that returns search suggestions.

The exercises are as follows:

  1. Become familiar with the application – both at an end-user level, and at the HTTP level. Record the script in HTML and URL mode, then try the Click and Script vuser type (at the time of writing, this vuser type will not correctly record the application).
  2. Create a script for this application. It should accept a parameter file that contains a valid search term on each line. Create the following transactions load_search_page, enter_character (called every time a character is entered in the search field), and final_search (where the Google Search button is pressed).
  3. Imagine that you’ve noticed an odd step-like pattern in the Percentile graph in LoadRunner analysis. You hypothesise that response times differ depending on how many characters have been entered in the search field. Modify the enter_character transaction name to include the length of the search term every time it is called.

Treat this with the same level of care that you would give a script that you were creating for a paying client.

I have added some notes and a solution script to the comments section of this post. If you are going to attempt this exercise, please do so before reading the comments.

FreeQueryBuilder – a better SQL tool

July 30th, 2006

Frequently moving between companies means that I sometimes find myself jumping from using Toad one week to Microsoft Query (yuck!) the next.

Now that I have had the chance to use it on a couple of different projects, I think that FreeQueryBuilder is a pretty good replacement for most of the SQL tools that I have had to use; and it certainly saves the effort of learning a new interface every time I move projects.

The best part of it is that it is shipped as a jar file, so you don’t have to install anything to use it – allowing you to bypass the week-long delay you are likely to experience at large companies waiting for the desktop support team to install software you need to do your job with.

FreeQueryBuilder/SQLeonado screenshot

Off the top of my head, the other things that make it a neat tool are:

  • It works with all the popular databases
  • Shows relationships between tables
  • Makes it easy to search through the data dictionary for table or field names
  • Allows you to write queries by clicking buttons instead of typing, but gives you a text editor option too

Give it a go!

Update: The FreeQueryBuilder project has been discontinued. The software is now known as SQLeonado, and has some additional features.

Developing a Methodology

July 23rd, 2006

A particularly fine roast hamSylvia is a very good cook. She makes a particularly fine roast ham, using a family recipe that begins, unusually, by cutting a section off both ends of the meat. One day, a friend dropped by while she was preparing the dish. “Why are you doing that?” he asked, as Sylvia carefully trimmed that ham, “Because that’s the way my mother always does it,” said Sylvia. But it got her wondering – why did her mother start that way?

A few days later Sylvia was at her mother’s house. “When you make that special ham, why do you start by chopping the ends off the meat?” she asked. “Because that’s the way my mother taught me,” came the response. Sylvia knew she had to get to the bottom of this. She picked up the phone and called her grandma. “Tell me Gran, when you used to make your roast ham, why did you always start by cutting the ends of?” The old woman paused for a moment in recollection. “Because I didn’t have a big enough pan,” she replied.

I’ve been thinking a lot about Methodologies lately, and the above story from New Scientist magazine (April 1st, 2006) makes the point perfectly that blindly following a process creates cases where you end up doing things that make no sense in a different situation.

Software pundit Joel Spolsky seems to discount the idea of having a Methodology at all – it can be replaced with a quality team of talented people with solid experience. But experience is a dear teacher; giving talented people something that will give them a framework and help them avoid the non-obvious traps has to have some sort of value, right?

Just about every methodology document I have read focuses very heavily on what to do. First you do step A, then step B, if condition C happens, then do step D. This prescriptive format is great if every project you do is exactly the same, but as soon as you encounter something different, you are cast adrift – doing things that make no sense, and groping your way through processes you have had to invent yourself to cover the gaps.

Because most Methodology documents usually seem to be written with one project in mind, they don’t generally bother outlining why the different activities are necessary – it’s probably considered pretty obvious when you only have a single project as an example. But if you explain the why, any halfway bright person can usually figure out the how for themselves. And, it’s harder to fall into the trap of rigidly following a process when it is clear which parts of the process are relevant to your situation.

My current feeling is that the core parts of a performance testing Methodology should fit on a few pages, and be built around some simple key principles like “find problems early” and “demonstrate value” (especially important for a consultancy company). Obviously there will be a need for supporting documents like templates and technical notes, but if it not possible to read through the core process in less than 10 minutes, then something is wrong.

I will let you know how my theories stand up to reality as I do more work in this area, but if anyone out there has any feedback or experiences they would like to share, it would be greatly appreciated.