How the Working Set Tuner Works

WST determines which functions are used together by starting with a measurement of your application. For WST to be effective, you must define a test scenario that will execute all the commonly used functions in your application. Your test scenario should spend the most time executing the most commonly used function.

Like CAP, WST is called every time a function in your application is called. Each function in your application is represented by a bit. This bit is set when the function is called. Periodically, WST takes a snapshot of all the bits, and then clears them. The default time interval is 1000 milliseconds, but you can adjust this. You may want to increase the interval if the scenario is very long, to reduce the time spent in the analysis phase. This should not effect the overall results very much.

The snapshot of the bits tells WST which functions were called during the last time interval. In sequence, the snapshots give a history of function references over time. Because the bits are cleared after every snapshot, a function with all its bits set is referenced on every snapshot. If a function had no bits set, it was never called during the test scenario.

The following table shows how this looks. We ran WST on the Solitaire cascade of cards. If we were really trying to optimize Solitaire, this is not the scenario we would use; playing a game would have been a much better choice. But playing a game of Solitaire is difficult to automate with testing tools, so we chose this simple case instead.

Before tuning After tuning
00000000000000000000000000000000
11111111111111111111111111100000
00000000000000000000000000000000
11111111111111111111111111100000
00100000000000000000000000000000
11111111111111111111111111100000
11111110111011110000100000000000
00001111111111111111111111100000
00101000000000000000000000000000
00001111111111111111111111100000
00001000000000000000000000000000
00001111111111111111111111100000
00000000000000000000000000000000
00001111111111111111111111100000
11111111111111111111111111100000
00001111111111111111111111100000
00000000000000000000000000000000
00001111111111111111111111100000
00000000000000000000000000000000
11111110111011110000100000000000
00000000000000000000000000000000
00101000000000000000000000000000
00000000000000000000000000000000
00101000000000000000000000000000
00000000000000000000000000000000
00100000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00001111111111111111111111100000
00001000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00000000000000000000000000000000
00100000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00000000000000000000000000000000
00100000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00000000000000000000000000000000
00001000000000000000000000000000
00001000000000000000000000000000
00001000000000000000000000000000
00001000000000000000000000000000
00001000000000000000000000000000

Each line corresponds to a function. Each function has a row (left-to-right) and each column of 1s and 0s represents a snapshot of each function's activity at that moment.

In the first column, the functions are ordered as they appear in the executable after a normal compile and link of the application. Not all the functions in the program are shown, just the ones at the start of the executable image. Each 0 or 1 corresponds to a Time Interval. The bit is 0 if the function was not referenced during that particular time interval during the cascade, and 1 if it was referenced.

The second column shows the routines that are at the start of the packing list after tuning the working set. These are all the routines that have their bits set during the test. The remaining routines in the image were not used during the cascade. Notice the string of routines near the bottom which had only one bit set. These occurred because we moved the mouse across the cascade while it was running. If we had not done this, these routines would have remained scattered throughout the image. If you automate your test scenario (which you should do unless you plan to do the test by hand every time your application changes), this is one time when some use of the mouse is a good idea. For most applications, you can test any screen resolution in your scenario. However, if the screen resolution affects the operation of your application, you should take the time to make your test independent of screen resolution.