Identifying Where Time Is Spent Using Profiling
As soon as it is possible to run the application with meaningful results, a runtime profile of the application should be collected. Profiling is important for multiple reasons, the most fundamental of which is that what is not measured is not managed. If the performance of the application is not monitored as it develops, then there is no mechanism to identify changes that impact the performance of the application. However, there are other reasons for doing this:
Verifying that the time is mainly spent in the functionally critical part of the code. Applications will go through multiple states at runtime, some concerned with start-up or teardown, but there will be a critical core of functionality that actually defines the purpose of the application. The time should be spent in the critical sec-tions of the code and not in the parts of the code that facilitate the critical code. Imagine an application that loads data from a database, performs some analysis of that data, and then produces a chart as output. Time spent doing the analysis is probably the critical purpose of the application, and the bulk of the time should be spent there. The other sections of code should be completed as quickly as possible. If this is not the case, then you might question the code used in those stages.
Depending on where the time is spent, this might be the method of retrieving the data or the complexity of the charts being printed.
n Avoid time spent in noncritical or error-handling code. A frequent performance sink for applications is code that shouldn’t be executed. This might be exception-handling code, writing error messages to stderr, or code that was meant to only handle corner cases. Once an application is profiled, it is relatively easy to identify sections of the code that were not expected to be visible in the profile.
n Checking the distribution of time between user, system, and other program states. Some applications will spend significant time in system code or some kind of waiting. System time might be necessary for the application to perform its task, but it can be an indication of something either going wrong or being poorly coded. An application might spend system time calling a heavyweight function to get the data for a time stamp when a lighter-weight alternative exists. Similarly, an applica-tion might spend significant time waiting for data to be returned across the net-work or waiting for the screen to be redrawn; performance might be improved by having a second thread carry on with computation while the main thread is in the wait state.
n Detecting time spent in exceptional conditions. These might be software traps to handle floating-point calculations involving subnormal numbers, or they could be something as mundane as TLB misses. These conditions are often hard to detect because they may not cause additional system time, but they are detectable either through observation using hardware counters or by careful examination of the exact assembly language instruction where the time is attributed.
Profiling applications as they are written and used is probably the most effective way of managing the performance of the application and should be routinely done during the development cycle as well as after any changes are made to the application.