Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2000-414
$eventId
ID of event: wwdc2000
$eventContentId
ID of session without event part: 414
$eventShortId
Shortened ID of event: wwdc00
$year
Year of session: 2000
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: ...

WWDC00 • Session 414

WebObjects: Performance Metrics

Tools • 48:49

This session discusses tools and techniques for collecting and analyzing application performance metrics such as statistics, events, record, and playback.

Speakers: Eric Bailey, Stan Jirman

Unlisted on Apple Developer site

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

We have with us Eric Bailey to discuss performance metrics, trying to squeeze even more information out of your application, and we'll try and squeeze some more information into your head as well. Enjoy the session. Okay. So, if I can get this to go forward here. There we go. I'm Eric Bailey in Internet Services at Apple, where we deploy applications like the Apple Store and iTools.

I'll be joined shortly by Stan Jirman, who works in the WebObjects Tools group. He's going to talk to you about some of the new features in WebObjects 4.5, which are going to help you measure the performance of your WebObjects application. The sessions have probably gone in the wrong order. We wanted to talk about performance first. How do you measure the performance of your application? Then when you find the problems, go and optimize it, which I think was this morning, and then deploy it, which was yesterday.

So, today we're going to talk about performance metrics. We're going to talk about how to measure the performance of your WebObjects application and improve it. We're going to focus in on your application and not all the other parts of your environment. And we'll discover what factors will influence the overall performance of that environment and help you pinpoint the code you can go and improve.

So you've probably seen a picture like this before which talks about the overall architecture of a very typical WebObjects application where here we see the HTTP request lifecycle comes in, gets served by the web server into a WebObjects application in the green area. A lot of the time it's hitting the database, information flowing back to WebObjects, back out through the web server, into your client browser.

The point of this slide is to show that there are a lot of factors that influence the overall performance of your application. It's not just inside the code that you've written in the action invocation business logic area of your WebObjects application. Other factors do come into play and it's important to note what all those are.

A lot of WebObjects deployments have a lot of other

[Transcript missing]

So today we're going to try to answer a few questions. How do I measure performance? What does it mean? And am I getting good results? We're going to go through Woe Stats, which is a very useful tool for getting started, and then move on into Event Logging, which is a new feature in WebObjects 4.5. It will help you get into finer-grained detail what areas of your application need your attention.

There we go. Thanks. So the web server at the top layer of this really acts as a load balancer in a WebObjects deployment environment. Its basic job is to forward the HTTP request onto an instance of your application. And in so doing, it's basically an I/O intensive task. You get down into WebObjects and then you may be making a request upon the database. All of the factors on the left are very important to note, especially database. And other sessions have talked about improving your overall database performance, optimizing EOF, making your queries more efficient.

And although a lot of us take it for granted, there's a lot of I/O network traffic going on. There's latency. All these play into the overall performance, like I said, and you want to not take these for granted. Once you take some measurements with nWebObjects in your database at the HTTP server layer and at the client end, you'll get a better feel for whether this is important or not. Usually it's not a problem in a lot of deployments, but nonetheless, after you've measured some If you need to talk to your sysadmins about tuning your routers or configuring something differently.

So the first tool that's built into WebObjects we're going to talk about is WoeStats. This has been in WebObjects for a couple of releases and it's a good starting point to figure out if your application is on the right foot. It's not going to get very fine-grained like event logging will, but early on in the development cycle you should take a look at WoeStats and figure out if Your pages are coming back. Your transaction times are acceptable. We'll talk about what's acceptable in a minute and what might not be acceptable.

WoeStats, like I said, is not very fine-grained. It measures transactions time at a high level. Basically, an HTTP request comes into the web server, forwards it onto your instance, and as soon as it gets there, Start the timer. As you can see here, the database is downstream of that request, so therefore all of the time taken to do a SQL query is going to be recorded in that timer. Once we actually finish sending the response out of your instance back to the WebObjects-based adapter embedded in the server, that timer will stop.

Woe Stats is in the Woe Extensions framework and it's always on, has pretty low overhead Well, it's not always on. You can turn it off. There's a Woe Statistics Store class in Woe Application which you can use to modify Woe Stats, customize it to your needs a little bit, and you could turn it off if you wanted to. This is a screenshot of the direct action called Woe Stats, an example URL above of how you would access it in the Woe Info Center application.

As you'll see in the screenshot, we have 17 overall transactions in the top left corner of the table. This is not many transactions, and I don't expect that you should read anything about your WebObjects application's performance with that few transactions. You want to get it warmed up. Touch all the areas of your application.

The first time you load a page, WebObjects has to read that component off the disk, initialize a few classes internally, and you really need hundreds and even thousands of transactions through your application before you get a sense of the performance. But here, we hit WoW Info Center a few times, 17 to be exact, and we had an average transaction time of 1.036 seconds. Now, that shouldn't alarm us because, like I said, you want more transactions, but that's not great.

I know that WoW Info Center, though, does some indexing at startup, and we would expect this to a certain degree. The next number over that's interesting, is the average idle time. I had this application running for a while before I took this screenshot, and here the idle time is hours, really. But this is the amount of time between requests, so how long your application sits idle.

This is a good number to use to get a sense in deployment. It may have been mentioned whether or not you have enough instances or too many. I know that on iTools we look at this number a fair amount to see if we need to add more instances.

You want to have it be probably, I don't know, it's a hard number to figure out exactly what you want it to be, but 10, 20 seconds is good. Higher than that is even better. If you expect bursty traffic, you're going to want to see the average idle time in kind of low or normal traffic modes be fairly high in the 20 to 30 second range so that you have enough instances that can handle a burst of traffic.

Moving down the page, if you scroll down, you'll see a couple of tables that detail the component actions and the direct actions. So in the component action statistics table on the left we see the name of the component being returned. This is important to note that in the diagram that I drew before, WebObjects application does take values from request, invokes an action, and returns a response.

The component that is being used to return the response is listed in the left column. So although we see in the menu component that the average was very fast, 18/1000th of a second, that was returning the menu page. So it also involves whatever was going on in your application when you took values, invoked an action, and then returned that component.

For instance, the main component is very slow, 1.306 seconds. Now, again, we don't have enough data to be for sure, and the thing that I would point out is notice that the minimum is 16 one-thousandths, which would indicate that it did fine on a few requests, and the maximum is 7.127.

So, like I said, I know WoW Info Center loads some indexes and figures out some things when it launches to better help you find documentation, so it has some warm-up time. So we'd really want to hit this application a thousand, two thousand times, and we'll talk about how to do that a little bit later.

So that was Woe of Stats and now I'm going to hand it over to Stan Jiurman who's going to talk about event logging which will help you get into more finer grained detail about where your application needs tuning. Hello. I'm going to tell you something about WoEvent logging, which is a new feature that was added in 4.5. WoEstat has been sitting around for a while, but this is a new feature and most people don't even know it's there, so I'm going to tell you about it.

It's way more fine-grained than WoEstat. It doesn't do just components. You can use it for logging any kinds of intervals. It allows you to identify the bottleneck of your app. Well, that's what performance tools are all about. And what's interesting, it's built into any 4.5 application that you are running.

Patience. That works. So what you're going to learn here, what is an event? What's the definition of an event? What are the built-in events? WebObjects comes with a lot of built-in events so that you don't need to do anything in your applications. How do you enable it? How do you read the data that it shows to you? And if you're really into it, how do you define your own custom events for tracking of your own application-specific things? I'm going to give up on this.

What are the prerequisites to use uEvent logging? Well, on any platform WebObjects 4.5 will have this enabled. You can connect to it with any simple web browser and you don't need to do anything. You don't need to link against a special framework or library. Just when the app looks slow, you just connect to it and find out what's going on right now.

What is an event? An event has basically a starting point and an end point. So within the framework we do most of those strategic places, database fetching, component rendering. We already have the start point there, then we do our own stuff and we have the stop point there.

And those events can be nested. Let's say we have a page and the page is being rendered. So the page is subcomponent. So we have the start of page and then, well, start of component one. And then the component is rendering itself and maybe needs to do a database access. So we have the database access in there.

All event logging is very, very efficient. There is, again, no special framework or library that you would need to link against. All event logging is programmed in line, so we don't do any objective-C posing or anything like that. All the analysis that you will see in the demo is done at analysis time, so while we're collecting the events, it's pretty efficient.

We have memory overflow protection so that when you, for instance, forget it turned on, it will not just run out of memory and kill your server that actually is serving customers. You might be thinking, "Well, performance and really efficient, what word is that?" On a 300 MHz G3, we can log 300,000 events per second sustained. That's something. Again, sustained. That can go on for hours, and we won't die on that.

There's no disk I/O involved. I know that it's pretty, these days, disk is very slow compared to what it used to be, relative terms. Also, the way it's done, it's pure C methods. We have some special handling how to do it straight in C instead of objective C and static Java methods for maximum performance.

Uh, some more numbers. We have a custom memory manager and garbage collector. And so let's say what's the worst thing that can happen to you? You turn on event logging and you just forget it turned on. And so the worst thing that can happen to is that you will waste four megabytes of memory per execution thread.

And our own memory manager will recycle this memory as time goes by. So the oldest events will be trashed and the newest ones will be used. And all of those levels can be set. So if you don't want to waste four megabytes just on one or whatever, you can set that in per default. Robustness. As we all know, nobody's perfect and our applications do tend to do bad things, raise exceptions. And we handle exceptions gracefully. For instance, you start an event and it's nested nicely deeply and within the database execution, you hit an exception.

Well, what's going to happen? The exception handler is way, way below and all those nicely opened events, they will not be closed but the exception handling mechanism will still catch it. And if the system finds out that for some strange reason something's going wrong, the memory's going away or something, it would just turn itself off. And that's on by default. You would really have to tell it not to do that. to turn itself off and continue logging.

The system is very complete. We have strategic places where events are built in. There's literally dozens of them. I didn't really want to list them all, but we have for EO adapter, regardless which adapter you have, editing context events, component events, again many, and for all pages and for all bindings.

We'll see that in a demo later on. The user interface for this tool is accessed through two direct action web pages through any browser. That's the WoEvent Setup page that is used to set up the event logging and the event display which is actually used for the data analysis.

Somebody's cell phone is working. I had no signal here. Events are grouped into groups that kind of make sense. Say, the database context event is a group of actually two events, objects with fetch specification and save changes. It doesn't really make too much sense to log one without the other. So they're grouped together and this way we have about a dozen of groups with a total of, you will see the setup page again, like three to five events per group.

The event setup page, again I'll go more in detail into that in the demo, is used to turn on or off the logging. You can also use it to reset logging, to clean the cache. And it will show a dynamic page of all events that are relevant for your application.

For instance, when you are using an Oracle adapter, it will not show the Sybase event. It will show only the Oracle event. And so on. So if you have custom classes, and you have even maybe your custom events, those will be listed. And if you don't, they won't show up. So it's all dynamic.

The Event Display page is again access to the Web Event Display Direct Action and it allows you to view the data, to collect the data in five different ways depending on what particular thing you're looking for. In the demo I will talk about three of those most useful ones.

So this is a more detailed example of Wolfie Maut encounter in a real application execution. This is the same slide as before. And say you have a main page and it does something and then within itself it builds a dynamic nested component and that component conditionally executes a database fetch. Maybe it might not need it, but maybe it might.

Compared to that, we have another page. It's the same page, but at that point the condition did not fire, and so there is no database access needed. Again, for comparison, we have

[Transcript missing]

There will be, we'll discuss three different ways to display the data. The most, the simplest one for when you're just starting to performance enhance your application will be view by page and then by component.

You have a page that has multiple embedded components and so you'll see the most expensive page on top, then you will see the, you open up the link and there will be more events in there sorted by component and you can drill down into those components. components into database access and whatnot.

There's another view, View by Page. It's very similar to the one, View by Page, and then Component, except it will show all the components flattened. So in a really sophisticated page, you might find yourself looking at a really long list, and it might be a little bit harder to find out which component, what database access happened.

But it's a more complete information, and you can still drill down into those supplements. And finally, the Unsorted view is also aggregated, so the same aggregation that I outlined initially would take place. But it shows you everything flattened out throughout your application, so you see really the worst thing right on top and the second worst thing. And I think this would be the demo.

So yeah, excellent. What we have here is the Think Movies, very popular with us on demos. I'm sure you've seen it before. That's what we ship. It's an example, purely written in Java, and we ship the source for that. So we have the homepage, we have the search page, master index, and what I'm doing now is just click around, let's search for S, submit query, stand by me. And we have the simple app. I'm not really going to talk about the app. What we want to see is like, let's say it's slow, and so we want to turn on event logging. So we go to the WoEventSetup page.

I hope I'm not the only one who thinks that keyboard is not the best on the planet. Here we have the list of relevant events for this application. We have the database context event, editing context event, application event, association event. That's the same as like a wall binding. It's probably a better name for that. Component and component reference event. So I'm just going to say select all. And, well, let's go back to the application.

and I'm going to play around. Because boys like to play. R-Wars, Master Index. Let's just click around, make the application do something. Here, scroll around a little bit. This will not be the most amazing event log, again, because we're not showing, we're not really exercising the app. I'll show you a page, star wab, with lots of really cute, geeky pictures. This is the WebObjects builder team, as it used to be back then when. And here we also have the EUF team. Look, I feel really special. I'm on both teams here.

So let's not leave the Wolf team out. All right? Look at this. This is a very beautiful picture. OK. And now let's see how the application did. WoEventDisplay. I proudly type with two fingers. Whoa, this one is a little bit too big. Does anybody know how to make the font smaller? Okay, well, I have a button on the tool, but not here. Okay.

It looks awkward, but we will go first to the Show by Page, then Component view mode. And here we see that all the pages that our application has touched during this brief exercise. We logged a total of 1374 events. 91 events of that was in EOF and 483 in WebObjects.

So we see again, I said we can log 300,000 events per second. And you see that was not that many events here. So you really don't get any performance hit. And when you leave it turned off, you don't get any performance hit whatsoever. So let's see what was happening in the Display Video page. We see that it has received 643 calls and it took 833 milliseconds in total. While the Display Set page got about as many calls but took only 42 milliseconds. So we know already where's the problem. It's in this page.

All right. And now it's sorted by component. This is a pretty lame example because this page is only one component itself. So let's assume there would be now more components. And here we see, uh-oh, Pretty much all of the time, 814 milliseconds out of the 833 were used in pulling the data for the actor image.

So, well, that was kind of to be expected because these are data blobs, but it shows you here, and I can again drill down, and I see that actually of all that time, most of it was in your binding. Most of that was actually in the Objects with Fetch Specification call within EOF. So you might want to look, maybe your fetch specification is not the most optimal one, etc.

The other display mode that I mentioned is the one grouped by page only. This will be only a very minor change. You see there is no component in their display video page, but if it were a real application with more components, it would actually be nice to have them sorted by component.

Otherwise, it can still drill down and you will see that the display video page is still in the same state. You will see the objects with fetch spec. The last one that I mentioned in the slides before would be the one aggregated hierarchical events, which is just without sorting, without any sort of hierarchy. And we see immediately that the data pool from the database is listed topmost. It doesn't need to even drill down anywhere. However, as you see, the list is getting longer and longer. And if we had more events, it would be a little bit harder to read.

And as I mentioned before with the aggregation of events, when we have a similar call graph that we actually coalesce all that, you see there's also the role mode that I usually don't want to click on because it would list this one 524 times on the web page. So this tool actually does a lot of work for you just by looking for the identical call graph and putting it together.

So so much for the demo. Can we switch back to slides? Now, what can you do, what if you need to customize it? What we've shown here, this is the stock event log in and we can customize it. It does already quite some stuff for you. But if you need to customize it, the events are very, very general. There are two basic superclasses, the WoEvent and the EOEvent, depending what you want to measure. You just can subclass that.

Our events are pretty much everywhere where it makes sense as you can see. Now let's say that you want to measure something very, very specific. Let's say that it was not the database fetch that took so long, but for some really strange reason your init code is taking so much time. In your init code you're doing only three or four things and you want to find out what's really so bad. What you can do is, this is a generic piece of code, or okay, awake, not init. You want to log your own stuff.

What you do, there's a global variable that's being set because we set, again, very efficient, so you do just a Boolean test. If event logging is enabled, then only in that case will incur that little bit of overhead. We'll create a new event, which is a static method, new event of class, just a normal event class. You can pass any string. You can pass any string as a comment to it.

As you saw in the table before in the demo, there's always comments that you can display. Then you mark the start of the event. We also have atomic events that just say, "Hello, I was here." They don't have any duration, but we will not really go into those.

Then you have your own code there that you want to profile. Then finally when you're done, if event is not equal null, or nil in my favorite, favorite language, then you mark the end of event and the system will automatically log it. It's possible that within your profile code here, you would have some other start and end event in there. Again, if you raise an exception, our own exception, garbage collector, in a sense, we'll take care of that.

An alternative, this was the cheap solution. Now let's go a little bit into the more sophisticated one. You can provide your own event classes. Say you want to log some really specific things about in which context were you called. You want not just like I was called and I took 15 milliseconds, but more I was called from this component or I was called from the other component. And you need to store some data in your instance variables. So you just create an empty class.

And that's good enough. And it will be automatically added to the runtime, and the system now knows that it exists. And then you just call it, oh, there's a required description file. That's a file, myComponentEvent.description. And there's only one mandatory field. That's the EOEventGroupName, which is my whatever event. And then do this, do that. I will go back to this screen. We see here EOEventCenter.markStart of event, event awake.

Now that's the key that you would be, that would be the do this or do that. And that's just for you as a programmer, a really short description. And what's going to be shown to the user in the whole table view of the event display will be the long, verbose description like, "I'm going to Operation #1 or another operation to be logged.

So this is the basic key value mapping. Only the group name is mandatory. When you don't supply the other fields, it will just take whatever you pass in as a string and you place it in the project resource suitcase and it will automatically be taken care of. I think that's about it for the event logging. I'll give back to Eric. Probably he knows how to operate this. The button that you showed me did not work. I had to start using left and right. Thanks, Stan.

So event logging is really neat and I'm looking forward to upgrading some of our applications from 4.0 to 4.5 just to get that feature and help us get into tuning our applications at that high level of detail. One of the things that Stan and I both commented on is that you need to do this under stress.

Sitting there and having one person hit the application and logging these events isn't enough. It doesn't give you enough detail. It doesn't tell you what's happening when your application is running. So the next topic we're going to talk about is a tool that's built into WebObjects. I refer to it as a playback and recording, recording and playback.

It allows you to generate load on your WebObjects applications and then the numbers that you've seen in WoeStats and Event Logging are going to turn into something that you can interpret. and it'll be useful in helping you forecast things like how many instances you're going to need, how much hardware you're going to need, and where to go from there in your deployment. A couple of things I wanted to go back and touch upon.

When you're doing this kind of testing and you saw that this measures using real time, you want to make sure that the system that you're testing on doesn't have a lot of other things running on it. If you have other servers running, you have other processes running, they're going to take time on the CPU and take up resources that are going to skew these results.

Okay. So playback and recording, as I mentioned, is a load testing feature built into WebObjects. I'm going to talk in a minute about what it's, what it's, what it's As I mentioned, it's load testing. I'll talk in a minute about what not to use it for because it's intended for some very specific things and I've heard and seen people misuse it.

Basically, what it does is record sessions. You use a browser, you click through your application, get the coverage of the pages that you want, and it records that session, saves out the raw HTTP requests and responses to disk, and then you can use those at a later time to play them back and simulate traffic.

So I emphasized load, right? Playback is intended for prototyping load and once you do this you get a good feel for how your application is performing when it's in a deployment environment. One client and one server doesn't really cut it. So once you start using the playback tool or some other tool, then you can access your application with the browser and see how it reacts with one instance on your development box. You can take this on to your QA or staging environment and see how it behaves there on the class of hardware that you're going to deploy on and get a feel for how it's going to work there.

So I'm saying it's free. Well, yeah, it's free if you have the product. There are other tools I'll mention in a few minutes that you could use that aren't free or that aren't bundled with WebObjects that do the same kind of thing and do other things as well. But Playback Manager is a great tool. Eric Bailey, Stan Jirman So I emphasized load, right? Playback is intended for prototyping load and once you do this you get a good feel for how your application is performing when it's in a deployment environment.

One client and one server doesn't really cut it. So once you start using the playback tool or some other tool, then you get a good feel for how your application is performing when it's in a deployment environment. So I think Playback Manager is a great start like Woe Stats is for getting a feel for how your application is performing.

The last point I want to make is that we've used it very successfully in Internet services and the Apple Store is an example of a high volume Internet site that we used the playback tool over and over, fine-tuned our application, continued to reuse it and ended up with a very stable application once we deployed it.

So, it's not a coverage tool, it's not for functional testing, it's not scriptable. Once you record that session, that session is going to get played back and you can't change that. You'd have to record many sessions to get coverage. And this, depending upon your application, can be very complicated. That's why I emphasized load before because if you're going to use it to try to get the coverage, you're going to want to use some other tool or create a custom script.

Another limitation is that it can't do very good validation on the results of your pages. So if you're sending back dynamic data coming from your database, you're going to have some challenges making it validate that that's okay. All it really does is compare page lengths and says, "Yeah, if this page is the same as this one, then I should continue on to the next HTTP request in the session." And it can get tricky to manage a high volume of virtual clients with the tool.

If you want to simulate tens of thousands of users, it's not going to scale up to your needs very easily. The playback manager can do this. It takes some of your time and investment to get into that and set that up. It also takes some hardware to do this. You're going to need more machines to simulate that kind of traffic.

So the first thing you have to do is make a recording. So here's an example. You just start Think Movies, the application that Stan used earlier, with this argument and give it a path to tell it where to record those sessions, where it's going to save those requests and responses.

Start your application, launch your browser, click through your application, and when you're done, stop your application. That's all you need to do in a session. Several files will be stored in a directory. There will be a directory created inside SlashTemp, like for example, thinkmovies.rec recording. And there will be all the HTTP requests and responses in there.

As I mentioned, there's a couple of options for playback. There's a command line interface, which I'll show you a screenshot of. And there's Playback Manager, which allows you to launch some Java

[Transcript missing]

So let's take a look at the screenshot of that command line interface. So here I took a screenshot of running this recording I did on Hello World. Hello World is a very simple application. It puts up a form and you type in a text and it sends the next request and displays a page that says hello whatever name you typed in.

Now, Another important thing about playback to mention, when you record this script, it's recording the raw HTTP. So if you entered in, in my case, Eric, for the Hello World example, every time it did that, it would send back the same text. So another limitation there is it's not good for dynamic data. There's some other tools that can take data and insert those into the forms in your WebObjects application and simulate more variety and coverage in your form posting.

I wanted to mention another thing on here. You see a number on the far left which is the total number of requests that the tool has sent. There's the time it took to receive that Response Back. That's the total amount of time measured from the client's perspective. Now, earlier we saw Woe Stats and we looked at event logging and we got numbers that were measured lower down in the stack.

Right? So, in this case, we're looking at 7/1000th of a second for request number one. If we look at, if we did the same measurement on Woe Stats, we should see a smaller number because there is I/O going on. The raw HTTP is being sent back and forth from the browser. That's going to take at least some time.

So, you can use these numbers to make sure that the numbers you're seeing on the server side make sense. And then that overall picture that I showed at the beginning, you're taking timings at the very top inside WebObjects as soon as a request gets in and is being sent back. And then you use event logging to go deeper in and analyze those smaller code fragments that you've written.

In the middle you'll see average, which is a moving average. And this is a good number to match up with one of those numbers at the top of Woe Stats, which tells you what your overall transaction time is. And then it shows you bytes. And I set a parameter you'll see on the top line to be very large. Basically, like I said, it does matching based on the page lengths.

And if your page lengths that it gets back don't match, then it considers that a failed transaction. And you'll see that all these passed. And you can have it ignore failures and keep going or You can have it stop when it gets to a page that doesn't match.

If your recording goes through your application and doesn't get into a lot of dynamic data, you don't have pages that grow based on how much data is in your database, you can set that percentage down a lot lower and get more meaningful results and actually use it for some validation. But that leads us into what other options are there. There are some third-party tools. We've used a few that will do more for you than playback can.

I know of a couple and I know there's some others out there. Mercury has one called Load Runner, runs on NT. RSW has one called eTestSuite which runs on NT as well. And used a little bit of each of those to do some testing and they're a lot better for coverage in that you can script. So you can write a script with one of these tools. Let's say for example an iCards application on our website.

You can have it go in and try to send every one of those cards and we can get better coverage and make sure all the images load. It's not doing what playback and recording is doing where it's just sending the HTML. It actually fetches all the images as well. So we can make sure that all of our images appear, we don't have broken links, etc. with a tool like this.

And you can write a script to do the coverage. So go touch every category in iCards, go try every card, make sure all the images are in there. images load, et cetera, et cetera. This obviously will help you with regression testing if your application is not changing too much or you've made a change that should not affect the user interface. You can use a tool like this to make sure that you have no new bugs.

and they're more flexible in the way that they do validation. So if you have a string that appears on a page that's an error, server error, error page not found, something like that, you can ask these tools, "Hey, if you ever see this string, report an error. I want to know about it." And you can have it, if you have dynamic data and your page gets much longer, you may have some text at the bottom of that page that signifies that this was a valid retrieval of data, this page is fine. You can say, "I don't care whatever else is on the page.

If you see this string, it's a valid response and we should continue on with the test." The other thing that you can do with these once you've set them up is put a box just outside your deployment environment, outside your firewall, and have it just sit there and execute a script every hour or two or maybe every couple minutes.

Make sure that your application is responding and doing the things that you expect it to do, which turns it from a testing and development tool into a deployment tool where you can check for response times, make sure your application isn't down. It's just unlimited with the scripting capabilities you could add to do some checking of your site.

So I want to wrap up with other factors that influence performance and talk about these a little bit. We're talking, back in the beginning I showed the architecture diagram. We were focused in on the green box, what you can do in WebObjects. And as I said before, when you do a test like this, make sure that you're testing something similar to what you're going to be deploying with.

Ultimately, if you can test in your deployment environment, that's the best thing you can do. If you have the same class of hardware that you're going to use in your deployment environment, use that. If your database is going to have a load on it from other sources, not just WebObjects, simulate that if you can. The more realistic you can make this environment for testing, the better results you're going to get from event logging and WoW statistics.

In the big picture, hardware, the CPU that you use, the amount of RAM makes a big difference. There's tools on all the platforms we deploy on that you can use to monitor how busy is the CPU. Am I utilizing this system very efficiently? Is it maxed out? Is it CPU bound? Memory Swapping Out to Disk. Check on Solaris there's something as simple as VMstat you can use to do that. There's been some other sessions that talked about database optimizations, advanced EOF.

You can do a lot of things there to improve your overall database performance. Obvious things, turning indexing on, and if you can influence the schema, you can make some adjustments there that are going to affect the overall performance. I'm not going to even go down too far into the single-threaded versus multi-threaded topic. I'll just tell you a little bit of what we found is that single-threaded apps do just fine, and the maintenance cost is very low. You don't get into more complexity.

A lot of the apps, in fact all the apps we deploy, are single-threaded and they perform just fine. Letting the operating system do the switching across multiple instances is sometimes just as good. It's not worrying about all the issues that go along with multi-threaded. Having said that, you can obviously run into situations where you have long-running requests and multi-threaded apps. apps may be your answer.

And as Stan pointed out with the event logging features, you can write custom events. My picture only showed a database. You could have other things, LDAP. You may be relying on reading and writing files a lot, other factors. Eric Bailey, Stan Jirman Write custom events, wrap those bits of code with custom events and figure out how those impact your overall system. The more information you have, you'll be able to influence the other parts of that picture that I drew earlier.

Eric Bailey, Stan Jirman Maybe your problem is not in WebObjects, but it's in your database or somewhere else. And the more data you have, you can go and optimize your code. And once that's done, it's somebody else's job. Eric Bailey, Stan Jirman Eric Bailey, Stan Jirman Hopefully we've given you a better idea for how to measure the performance of your WebObjects application, how to dig deeper, get some numbers. I'll invite Stan back up here and we can take your questions.