This page explains few details how Clover code instrumentation works and how the coverage data is being collected at runtime.
This article might be helpful for you in case you have significant performance problems or your application runs in a restricted environment.
Every time Clover instruments the code (via <clover-instr/> or <clover-setup/> - both Java and Groovy) it records information about the code structure (packages, files, classes, method, statements, branches, test methods etc) into the Clover database. Because of fact that the same database can be used multiple times (for instance in case of incremental compilation; or when project has several modules compiled separately), it maintains history of changes in blocks named 'instrumentation session'.
Every instrumented class is enhanced by adding code which requests a Clover's coverage recorder instance. Such coverage recorder getter is called with some arguments, which allows to determine which Clover database file and which instrumentation session in this file contains information about the class structure (like indexes of statements, methods, branches etc).
As project contains many classes, Clover has an optimization so that some of these classes will share the same coverage recorder instance - exact strategy depends on selected recorder type - see below.
Diagram: code instrumentation process
Information about code structured is stored in Clover database. Every instrumented class contains information about database (initstring) and the instrumentation session time stamp. Thanks to this it's possible to map compiled class file to a corresponding source file (also in correct version - see C.java).
This is a default coverage recorder and we strongly recommend using it.
It's using an in-memory fixed-size long[] array for recording hit counts for methods, statements and branches. Calculation of the long[] array size requires access to the Clover Database (clover.db) at runtime, however. All classes which were compiled in the same instrumentation session (i.e. within the same <clover-instr> or javac or groovyc call) will share the same instance of the coverage recorder.
This recorder simplifies a deployment and test process as clover.db is not required at runtime. It's useful for cases like in-container tests, tests executed on application server, builds on remote agents or for Android applications.
It's using a dynamically resizeable two-dimensional long[][1000000] array for recording hit counts for methods. Thanks to this it does not require access to the Clover Database at runtime and this is its main advantage. It's performance is slightly lower than the Fixed Coverage Recorder due to memory allocation and two-level indexing. All classes which were compiled in the same instrumentation session (i.e. within the same <clover-instr> or javac or groovyc call) will share the same instance of the coverage recorder.
Use this coverage recorder only in case when:
It's a modification of the Growable Coverage Recorder designed specially for Grails-based projects. It shares the same coverage recorder instance for every instrumented class which was compiled with the same database initstring and configuration settings (like flush policy). It means that it ignores instrumentation session timestamps.
Grails build system works in such way that it compiles every domain class and service class separately. As a consequence, Clover "sees" this as a separate instrumentation session. It means that in case of the fixed or growable coverage recorder it creates a separate instance of the recorder for every domain or service class.
It might become a performance problem if you have many such classes and you execute test methods, because end of every test method will force creation of the per-test coverage file (clover.db*.s) from all coverage recorder instances. For example:
Note that the performance problem does not occur during normal application run or when test code is not instrumented. For example:
If you decide to use a Shared Coverage Recorder, you must keep in mind that: