The publication presents a software implementation of built-in tools for collecting and accumulating metric information on the runtime of applications written in C / C ++ / C #.
The essence of the described approach is based on the inclusion of “control points” in the program code of the application for extracting data on the execution time of structural components: methods, functions, and {} blocks. The extracted metric information is accumulated in an internal database, the contents of which at the end of the application are converted into a text report form stored in a file. The appropriateness of using the means of built-in control of the execution time is due to the need to identify problem areas of the code, to analyze the causes of the temporary degradation of the application: full or partial, or manifesting on certain sets of source data.
The given examples of C ++ / C # source codes demonstrate possible implementations of the described approach.
Introduction
The development of a software application at each iteration (for example, the release of the next release) of its evolutionary development includes the following basic steps:
- development and testing of functionality;
- optimization of consumed resources of RAM;
- stabilization of runtime metrics.
These steps require a significant amount of developers not only creative (such as the development and implementation of effective algorithms, building a flexible software architecture, etc.), but also routine work. The latter category includes activities aimed at stabilizing time metrics for application execution. In many cases, this is a rather painful procedure, when developers are faced with degradation, which is a consequence of expanding the functionality of a software product, rebuilding the software architecture, and the appearance of new threads in the application. At the same time, the sources of degradation require certain efforts to detect them, which is achieved not only by the high industriousness and responsibility of the developers (a necessary condition), but also by the composition of the tools used for these purposes (a sufficient condition).
One of the effective approaches to solving the problem of analyzing application time metrics is the use of specialized software products, for example GNU
gprof . The analysis of reports generated by such tools allows you to identify “bottlenecks” (class methods and functions), which account for a significant amount of time spent executing the application as a whole. At the same time, the validity of the time spent on the execution of methods and procedures is certainly qualified by the developers.
It should also be noted that the software products of this class, as a rule, perform a metric analysis of the execution time of the program code at the levels of the methods of classes and functions, ignoring the lower (but nonetheless significant from the point of view of the analysis of the problem) levels:
{...}, for, while, do-until, if – else, try-catch blocks, inside of which no less significant expenditures of execution time occur.
Next, the main content of one of the possible solutions for the implementation of built-in control of execution time tools aimed at extracting and accumulating detailed information on time metrics of controlled software blocks with subsequent generation of reports for developers is considered.
Methods for Retrieving Runtime Data
The functionality of any software application can be interpreted as an
abstract machine with a finite set of unique
states {St} and transitions
{Tr} between them.
In the framework of this approach, any flow of execution in the application should be interpreted as an ordered sequence of its states and transitions between them. In this case, the estimation of the execution time costs is carried out by summing the time metrics over the entire set of passed states with ignoring the costs of transitions from one state to another - as negligible values.
The extraction and accumulation of data on the execution time of the application at the specified control points is the main task solved by the built-in control tools described below.
For each breakpoint declared in the source code by placing
PROFILE_ENTRY C ++ macro, the number of its passes during application execution is recorded, as well as the time metric - the total time the application was in the state from the moment the checkpoint passed to the next level of the program hierarchy (including a block, class method, function, etc.) as illustrated in the diagram below.
Control of control points (initial registration and calculation of their time metrics) is performed by the object
'timeManager' , which is created in a single instance. Each event of passing the checkpoint is fixed by the object
'timeManager', and during the first pass it is registered by it as observables as
'registerEntry' .
At the moment of each passage of the control point, a
timerObject object is
created , fixing the time of its creation. The execution time is fixed at the checkpoint when the application exits from the current level of the software hierarchy. At this moment, the timerObject of the object is automatically destroyed, which is accompanied by the calculation of its “lifetime” T. As a result, the
timeManager increases the number of times the checkpoint passes and the time spent in it by
T. For all set control points,
timeManager accumulates data with the subsequent release of a report when the application terminates.
Below is the source C ++ code that implements the built-in tools for controlling the execution time of the application.
The structure of the demo application is illustrated below, illustrating the use of the built-in runtime control tools as an example, as well as a table of the results obtained (for details, see
Appendix 1. Source code for the demo application ).
Section
Addendum 2. The source code of the means of the built-in control of the execution time of the C # application presents a similar implementation of the means of the built-in control in C #.
The author uses pairs of
TimeWatcher.StartWatch () and
TimeWatcher.StopWatch () when profiling the execution time of laborious (from a computational point of view) methods and procedures as part of the software product developed by
EREMEX Delta Design - a computer-aided design system for electronic equipment.
Below is an example of a brief report on time metrics of one of the functionality of the mentioned product.
Brief conclusions
The described tools can be used to collect data on application execution time in various parts of its program code, in particular, they allow:
- collect and accumulate data on time metrics of execution threads in the application;
- perform estimates of the execution time of program code accurate to elementary language constructs;
- manage the volume of extracted data by turning on and off the built-in control tools on the corresponding sections of the application execution threads
- develop and apply regression tests that monitor the stability (and detect degradation) of application time metrics.
In conclusion, it should be noted that outside the scope of this publication there were questions of the use of the described built-in controls in the context of
multithreading applications and no analysis of the accuracy of the obtained data by time metrics was presented in any form. The latter is due to the fact that in practice, when identifying the causes of temporary degradation of an application, the data on
the relative distribution of the execution time costs between the software components of the application are primarily relevant
. In this regard, questions of the accuracy of the data obtained are fading into the background.
Appendix 1. Source code for the demo application
INITIALIZE_PROFILER int main(int argc, char * argv[]) {
Supplement 2. Source code of built-in runtime control C # applications