xWeb Performance Tuning
This topic outlines general tips for optimizing xWeb performance.
Authenticate
- Call Authenticate as little as possible. xWeb use a session-based xWeb object so we can continue to reuse the authentication token instead of having to authenticate for every call.
- See xWeb Performance Authorization for more tips.
GetQuery Performance
- Cache data in your application side when appropriate. There are several places where the xWeb call returns data that doesn’t change very often, such as the list of address types or an event calendar. To reduce calls, I had the demo application write a local XML file that stores the results of the call for future calls so it doesn’t have to ask for that data again.
- Only ask for fields that are needed. It makes a big difference. If '*' is passed to szColumnList then GetQuery will instantiate the object and select each record, which can cause huge performance problems. Do not ask for more fields than needed, as this forces xWeb to include extraneous table joins that may slow down the call.
- Request only the results truly needed in GetQuery. Try to be as precise as possible in the szWhere clause so as to only get results that are needed.
Data Caching
In a mature NetForum system, many data elements will change rarely if ever (such as name prefixes and suffixes). Some data elements can change more regularly (such as product lists). And some data can change by the minute (such as event registration counts).
Ideally, your integration should strike a balance between caching data that changes rarely and getting up-to-the-minute real time data.
Take, for example, prefix and suffix codes. Once an organization sets up their prefixes (Mr. Ms, etc.), they will rarely add new ones. Suppose you have a page on which a user can update information about themselves. You might have the prefix and suffix codes populated in drop-down lists. Rather than call NetForum xWeb every time to get a fresh list of codes that might almost never change, consider implementing a procedure that gets this list on a regular interval. Hourly is fine; the point is to not call the method over and over as this will slow down your application and web page load with multiple round-trip requests to and from xWeb and also slow down xWeb in general.
Consider this most carefully for high-traffic pages that might conceivably need to call multiple web methods to get all the necessary data from NetForum. Suppose you have a page that outputs sessions and speakers for an event and suppose this page gets a lot of traffic. It might require calling several web methods to put together all this data. You don't want to call these methods over and over for every page load. Instead, implement a routine that gets this information from xWeb on a regular interval and cache the data locally in your system. Even if you call this data once a minute, that's acceptable and is a vast improvement over calling the data on every single page load.
Ideally, the routine that calls xWeb for this data should be separate from the ordinary web application so that the one user whose page load might trigger the refresh does not have to wait. Instead, implement a server-side routine that calls xWeb and regularly fetches data from xWeb and caches it to local data. This way, ordinary page loads for the event listing won't need to connect at all to xWeb except for web methods that are very specific to a particular user (such as getting a list of that individual's email addresses, for example).
How do you know when data is fluid or not?
This is difficult to answer, and it may be different from one NetForum site to the next depending on the usage patterns of the organization using NetForum.
Generally, any web method that has zero or few parameters, or which has no parameter for a specific Customer Key (which might trigger more specific filtering that cannot be cached universally), might be a candidate for caching on busy pages.
If you do implement a caching routine, how often do you call xWeb to refresh the data?
You can retrieve fresh data every few minutes or so for more fluid data, and perhaps hourly for more static data (prefixes and suffixes, for example). The point is not to try to call the method only once a day -- the point is to NOT call ten methods on every page load, especially if 8 or 9 of those methods are going to return the same data over and over for each user page visit.
A busy xWeb site may have thousands of calls per minute. It won't make a difference if you update prefixes and suffixes once a day or once an hour, so go ahead and update them once an hour if you want to. Again, the point is to engineer your integration so you don't call multiple web methods on every page load and the point is that you don't call the same generic web method (get a list of event sessions for example) over and over for different users who are accessing the same high-traffic web page.
Design for Data Caching
This is a summary of how you might design your integration to work with data caching.
First, let's assume you have a web site application that serves up and writes data to NetForum. By default, you would probably have code on each page, or in a business layer, that instantiates a web reference to xWeb and calls various xWeb web methods.
To implement data caching, you might instead do the following:
Create a middle tier business logic layer that is separate from the UI layer. All web pages that would normally call xWeb web methods will interface to the middle tier instead of to the page itself. You'll probably have functions/methods for each request or response (e.g. getting a list of events, getting a list of prefix codes, writing a new address to NetForum, etc.).
Next, in this middle tier layer, for all the "get" methods that retrieve data, you will need to determine if that list of data can be made static or must be real-time. See the section above for how to make that consideration.
If the data you are getting must be real-time, then simply call the xWeb web method and return the data.
If the data can be cached in some way, then let's look at how to cache the data.
You must make your own determination about how to cache data in your application and environment. For example, you might want to cache data in local XML files. You will write the files and read from the files on a regular basis. Alternately, you might cache data in memory or even write it to a simple database. The main consideration is that you want the data to be as close to the application as possible for minimal latency and fast reads.
Next, where does the application cache the data? To follow a MVC model, we recommend creating a new application (whatever that may be in your environment) that is separate from the web application. That application doesn't even need to be a web application -- it should exist solely to consume web methods and write the results of those web methods to XML files (or whichever caching routine you choose).
Suppose you're getting a list of prefixes. You'll call WEBIndividualGetPrefixes and that method will return a list of prefixes in XML. Take that list and write it to an XML file on the web server. Come up with a good naming convention for how this will work. If you are calling a method with parameters (such as an Event Key) then embed this key into the file name of the XML so that each XML file will have a unique name.
Set up the application so it will continually refresh the data on a particular interval. This interval might be different for each type of request.
Next, the middle-tier application will be coded so that it will try to get the data from the appropriate XML file, instead of calling xWeb directly.
Design Principles:
- Separate the retrieval of the data on the web page from the getting of data from xWeb
- Web pages needing xWeb data should never have to wait for the data from xWeb; that data should always be local (except for personalized data or data that must be real-time).
- The web application should be separated from the application that gets data from xWeb
- The cached local data generated by the application should be "close" to the web application for minimal latency
More Advanced Design Principles:
- Enable a routine to be switched from caching to real-time (or back) in case it needs to change for any reason.
- Enable each routine to have its own setting for how often to get a fresh list of results.
- Ensure that when you overwrite a cached XML file that you're not blocking the file when other methods are trying to open it.
Here are some code examples in .net.
Method to GetPrefixes. This method will be called by the web page to populate a drop-down list of prefix codes. The method should exist in the middle tier application:
public Array GetPrefixes(){ Array arrPrefixes; if(MethodIsRealtime("GetPrefixes") ) { arrPrefixes = GetPrefixesFromXWeb(); } else { arrPrefixes = GetCachedPrefixes(); } return arrPrefixes;} public bool MethodIsRealtime(string methodName){ bool bMethodIsRealtime; // look at configuration settings to determine if a method should be real time or not return bMethodIsRealtime;} public array GetPrefixesFromXWeb(){ Array arrayOfPrefixes; arrayOfPrefixes = GetXMLPrefixesFromXweb(); return arrayOfPrefixes;} public XmlNode GetXMLPrefixesFromXweb(){ // this method calls xWeb and gets the data and returns it. return xWeb.WEBIndividualGetPrefixes();} public array GetCachedPrefixes(){ string fileName = "WEBIndividualGetPrefixes.xml"; XmlNode oNode = LoadXml(fileName); return GetPrefixesFromXWeb(oNode);}