To write a bench method, you subclass the standard bench class
EsbBench. The new subclass is stored in the library and is
visible to all Smalltalk browsers. Next, you write a method in the new
subclass. Bench methods must start with an uppercase letter or they
will not be visible from the Stats user interface.
![]() | Because the Stats tool has fewer editing features than a Smalltalk browser, you might write the methods in a Smalltalk browser. |
A bench method is a Smalltalk method that contains selected code from an application program. Areas of interest are timed using instances of high-precision software timers, which are available as inherited instance variables of EsbBench.
EsbBench provides inherited instance variables, which are automatically initialized and ready to use in all subclasses.
Note: | EsbBench reimplements the class method new to send initialize to the new instance after it has been created. Any subclass of EsbBench must send super new when reimplementing new, and super initialize when reimplementing initialize. Failure to do so causes the inherited instance variables of EsbBench to be uninitialized, and the Stats tool will not execute the method. |
See Timing sections of code for an example of how to use the instance variables. The instance variables are as follows:
The following is an example bench method that measures the speed of an operation to open a window:
EtClassesBrowserNewOpen "Bench EtClassesBrowser new open." | w | name := 'EtClassesBrowser new open'. iterations timesRepeat: [ benchTimer start. w := EtClassesBrowser new open. benchTimer stop. w close].
Using benchTimer, you surround critical portions of the code. The above example includes the time to open a window but ignores the time to close it. The iterations loop surrounds the start and stop messages to benchTimer, allowing benchTimer to collect statistics on every iteration.
In the case of operations that take less than one millisecond, have the start and stop messages surround the iterations loop. The loop must be included in the operation because the time to execute the operation is so short that it cannot be measured from Smalltalk. To remove the cost of the loop and any other fixed cost of the operation, use the differenceTimer.
The following is a bench method that measures the speed of a very short operation:
SendDropDummy "Send and drop #dummy for a specific number of iterations." name := 'self dummy'. self dummy. benchTimer start. iterations timesRepeat: [self dummy]. benchTimer stop. differenceTimer start. iterations timesRepeat: []. differenceTimer stop.
Note: | Bench methods, such as the one above, are usually needed only when benchmarking primitives or low-level virtual-machine operations. Timing very short operations, such as a message-send operation, requires extra care. |
Writing a bench method has the following advantages over repeatedly executing the expression Time millisecondsToRun: [...] in a workspace and viewing the results:
This means that the code is managed by IBM Smalltalk. You include any application code that is needed to set up the initial conditions for the benchmark and all code is captured in the database. This makes benchmarks accessible to other members of the team.
Code is monitored by gathering statistics while the code is running. Execution is controlled by configuring the initial and current state of the Smalltalk virtual machine. The time to scavenge and to perform global garbage collection can be filtered from the raw time and viewed separately.
The Stats is unobtrusive; raw stack data is gathered while the benchmark code executes but is not analyzed until execution completes.
While bench code is often built and executed through the Stats user interface, it can also be constructed from other browsers and executed without the user interface. Over time, while optimizing the code, the programmer builds up a suite of benchmarks, which can be run periodically to ensure that code does not become slower.
This means that code executed in a method produces a more accurate measure of the actual execution time than does the same code executed in an expression.