Java Reference
In-Depth Information
using a short but nonzero sleep would be slower but more reliable.) The method in Listing
12.10 transfers credits from one account to another; between the two update operations, in-
variants such as “sum of all accounts equals zero” do not hold. By sometimes yielding in
the middle of an operation, you may activate timing-sensitive bugs in code that does not use
adequate synchronization to access state. The inconvenience of adding these calls for testing
and removing them for production can be reduced by adding them using aspect-oriented pro-
gramming (AOP) tools.
Listing 12.10. Using Thread.yield to Generate More Interleavings.
12.2. Testing for Performance
Performance tests are often extended versions of functionality tests. In fact, it is almost al-
ways worthwhile to include some basic functionality testing within performance tests to en-
sure that you are not testing the performance of broken code.
While there is definitely overlap between performance and functionality tests, they have dif-
ferent goals. Performance tests seek to measure end-to-end performance metrics for repres-
entative use cases. Picking a reasonable set of usage scenarios is not always easy; ideally,
tests should reflect how the objects being tested are actually used in your application.
In some cases an appropriate test scenario is obvious. Bounded buffers are nearly always used
in producer-consumer designs, so it is sensible to measure the throughput of producers feed-
ing data to consumers. We can easily extend PutTakeTest to become a performance test
for this scenario.
A common secondary goal of performance testing is to select sizings empirically for various
bounds—numbers of threads, buffer capacities, and so on. While these values might turn
out to be sensitive enough to platform characteristics (such as processor type or even pro-
Search WWH ::




Custom Search