-
Notifications
You must be signed in to change notification settings - Fork 18
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Coverage collection at the end from .acv files is taking significant time #175
Comments
Exactly what is written to the The output to file is buffered and compressed to reduce the file I/O bottleneck impact upon the system being tested, with the size on disk per visit record being dependent on the compressibility of the visit stream. Multiple such files are a result of concurrency handling measures; for example separate For a simple visit process (e.g. one pass through most code), the compression makes each {module,line,count} visit around 12-13 bytes; but in instances where there is a tight loop with a great deal of repetition in the output stream, compression ratios down to tens of visits per output byte have been observed. A 300Mb file would thus represent at least ~25 million distinct visits, but potentially several billion. If you are using the command line, Alternatively, the Another approach would be to identify any hot spots, and arrange tests of the hot spots to be separate from the tests of the rest of the system (run with the hot spot types/methods involved being excluded from coverage), combining them all in post-processing. |
Finally got around to doing some performance testing, and with a program dominated by a tight loop - let n = 1000
for i in 1..n do
for j in 1..n do
use s = new System.IO.MemoryStream(1024)
use b = new System.IO.BinaryWriter(s)
for k in 1..n do
System.DateTime.UtcNow.Ticks
|> b.Write generated a > 300MB .acv file, which I processed on old, low-powered hardware and got
so it doesn't in fact look like the bottleneck is in the unpacking of the coverage data - indeed with a smaller test set, the throughput was lower
as the fraction of time spent unpacking dropped. Bearing all that in mind, the likelihood is that the issue reported here is a result of the size of the code being covered - and the consequent scaling of the in-memory representation of the report as it's being filled in - of necessity, a random-access thing. So, rather than just the size of the I've not done any comparisons at scale yet to compare the performance of the JSON representation vs the XML one, so cannot advise whether that might be another thing to try; but in any case the points made earlier -- reducing the number of data points collected and partitioning the testing across units before aggregating will still speed the process up. |
Hi Steve, Thank you for sharing the detailed insights about the time performance metrics with a quick test-set. We appreciate the observations provided in the comment. We also believe that a huge code repository can create a difference, i.e. introduce significant time latency while collecting the code coverage. We might need to look into how we can minimize the data points collected (need to investigate further into this). May be we can start partitioning the testing modules and club the coverage collected at the end, all in parallel, that seems a good way ahead. We will post the update how it goes! Thanks again! |
Just to confirm, there's no AltCover specific setting to speed up the coverage collection process, right? As per our understanding from the documentation. |
Quite a bit of a difference from opencover from coverlet vs altcover coverage reports taking a huge time |
@SteveGilham Any insights on what could be done here ? |
I see the instrumentation takes the quite long time compared to open cover with coverlet |
Up front, I don't think I can offer any quick wins with this, except that if you're getting many (hundreds or more) visits per location, there is some speed-up to be had from using the At the moment I don't have any clear indications of hot-spots; and any ground-up rewrite would be at best speculative. Can you indicate some metrics for the size of the work you're doing - how many kloc, how many total visits, that sort of thing. |
This comment was marked as outdated.
This comment was marked as outdated.
@tilak-nanavati-opshub removed |
As well as the discussion here (and in #225) regarding the use of In particular, this includes
|
@SteveGilham we have some big repos where the instrumentation takes quite a long time. Would you like more logs or examples to give you more insights? |
AltCover deliberately doesn't dump much logging information (so it can't leak any end user secrets), so there's not a lot can directly be done. However, being prompted by your request, and having profiled part of the code for a newly introduced problem, I have now profiled AltCover while self-instrumenting, to find that almost 60% of the time is spent dealing with branch-points - an unexpected result, but one which gives me a definite place to start working. |
Release 8.8.173 removes the hot-spot that was taking most of the instrumentation time. |
Related to the main issue - having profiled the AltCover self-tests, there are no simple hot-spots like there were in the branch cover instrumentation, however
While there are use cases for both eager reporting (e.g. in cases where end-of-process handling is insufficient, such as using VSTest.exe without the AltCover data collector, and possibly in some cases of multiple AppDomain processing) and for recording every visit (though profiling is better for determining hot-spots), those are probably less common. I intend to take the net9.0 release be an occasion to make a major 9.0 release of my own, which will make --defer and --single the default behaviours and the equivalent breaking API changes, as well as any other house clearing that comes to mind. |
@SteveGilham here are some logs why does coverage statistics take that long time ?
|
Quick answer - it spends a lot of time deserialising the coverage data. Long answer - it depends on how you configure coverage collection. The default configuration opts for robustness of data collection over speed. In particular, that means eagerly writing every visit individually, rather than waiting for a If you know that the This used command line
this taking advantage of injecting a data collector into the VsTest process which is allowed to run to completion to output coverage data. If |
As a data point for the effect that Beyond that - the total size of your system under test is about 30x the largest that I have - the AltCover self-test - and in that case, even a linear scaling of the XML processing time with number of elements would lead to expected processing times in the 10s of seconds, as observed. The analysis of that part of the process showed that it was dominated by the needful operations - loading & saving the report, and in between, writing the updated attribute values - so a scaling by the number of records would be expected. |
On reflection - there is one useful set of logging that could be provided above and beyond the raw times of coverage processing; and that is a performance profiler run of the collection phase of the test process, or at least a flame-graph showing the portions from the AltCover.Engine assembly and below. Amongst other things, that would answer the question about where the time is being spent. |
We already use |
How can i use defer i don't see an option here https://stevegilham.com/altcover/%60dotnet-test%60-integration |
Thank you for at last providing some specifics - the actual command line - rather than talking generalities and getting generalities back.
Appropriate use of |
@SteveGilham if i try to use lcov instead of the cobertura reports the system slows down much more |
Duly noted, and will add that translation to the things to profile. In general, though, use of a native format (NCover 1.x, OpenCover or, now, the coverlet-based JSON) is to be preferred over the lossy formats like cobertura and lcov, not least because those involve a data translation step from from a native format. |
Makes sense. |
For the LCov case, profiling shows that the bottleneck is in the brute-force process of finding for each source file, which methods does it contain. I can see ways to ease that, even if it does make the code more complex and less declarative than it currently stands. |
As this issue has become hopelessly muddled, and the new 9.0 release includes the fast options by default, amongst other various clearing of bottlenecks, I'll close it now. |
Hi Steve,
Altcover is working great. capturing the coverage of all the instrumented DLLs, but recently we have observed that the .acv files are growing and reaching ~300 MB, (and there are multiple such files), from these while collecting the coverage, it is taking a significant amount of time.
Observation: A file (~300 MB in size) takes more than 48 mins.
Is there any way we can reduce this time?
It would be a great help.
Thanks!
The text was updated successfully, but these errors were encountered: