Open Bug 1322663 Opened 8 years ago Updated 2 years ago

Add Code Coverage endpoints to Debugger Server

Categories

(DevTools :: Debugger, enhancement, P5)

enhancement

Tracking

(firefox57 fix-optional)

Tracking Status
firefox57 --- fix-optional

People

(Reporter: jlast, Unassigned)

References

(Blocks 1 open bug)

Details

Attachments

(1 file)

This bug is about adding code coverage support to the debugger server, so that the client can fetch code coverage information with the script API: script.getOffsetsCoverage.
Assignee: nobody → jlaster
Blocks: 1176880
Status: NEW → ASSIGNED
Priority: -- → P2
Attached patch cov2.patchSplinter Review
This is a WIP. The two big questions I have are: 

1. when should I enable coverage. Based on prior discussions, I believe we should update the threadClient endpoint so it starts and captures a recording

2. how should we handle naming and signatures. This is something I threw together quickly and we can discuss here.
Attachment #8817588 - Flags: review?(jlong)
Nicolas, curious to get your thoughts on the API.
Flags: needinfo?(nicolas.b.pierron)
Comment on attachment 8817588 [details] [diff] [review]
cov2.patch

Review of attachment 8817588 [details] [diff] [review]:
-----------------------------------------------------------------

The main problem is that the recording is on by default. The UI needs to turn recording on explicitly so there isn't a default perf overhead whenever you open the devtools.

Thanks for working on this though, it would be nice to have!

::: devtools/server/actors/script.js
@@ +464,5 @@
>        // Keep the debugger disabled until a client attaches.
>        this._dbg.enabled = this._state != "detached";
> +
> +      // start code coverage
> +      this._dbg.collectCoverageInfo = true;

Yes, as you mentioned in your comment, you don't want to turn it on by default. It should be default off so there is no overhead, and some sort of UX figured out to "record" coverage and only turn it on when recording. You'll need additional RDP methods for that.

::: devtools/server/actors/source.js
@@ +626,5 @@
> +  hitCounts() {
> +    let source = this.source || this.generatedSource;
> +
> +    if (!source) {
> +        return;

Don't return undefined, return the same type as the function expects.

@@ +635,5 @@
> +    let hitcounts = {};
> +
> +    scripts.forEach(script => {
> +       let coverage = script.getOffsetsCoverage();
> +       if (!coverage) return;

Avoid early returns where possible; here just do `if (coverage)` and wrap the code. Early returns end up making code hard to follow.

@@ +638,5 @@
> +       let coverage = script.getOffsetsCoverage();
> +       if (!coverage) return;
> +
> +       coverage.forEach((data, i) => {
> +         hitcounts[data.lineNumber] = Math.max(hitcounts[data.lineNumber] || 0, data.count);

Are you sure this is correct? I would assume that the script has the number of times itself has been hit, so you should take the max of all the scripts on the same line, you should add them together.
Attachment #8817588 - Flags: review?(jlong) → review-
> so you should

That should be "so you shouldn't"
(In reply to James Long (:jlongster) from comment #3)
> ::: devtools/server/actors/script.js
> @@ +464,5 @@
> >        // Keep the debugger disabled until a client attaches.
> >        this._dbg.enabled = this._state != "detached";
> > +
> > +      // start code coverage
> > +      this._dbg.collectCoverageInfo = true;
> 
> Yes, as you mentioned in your comment, you don't want to turn it on by
> default. It should be default off so there is no overhead, and some sort of
> UX figured out to "record" coverage and only turn it on when recording.
> You'll need additional RDP methods for that.

The code coverage data is collected by default in Baseline compiled code, but not in Ion, nor the interpreter, unless this Debugger flag is set to "true".

Setting this flag to "true" will slow down the interpreter by ~2x.  Baseline code is already instrumented with code coverage counters for Branch Pruning optimizations.

Ion seems to be lacking instrumentation, and does not seems to be disabled as well.  I will write a test case to ensure that we disable/instrument Ion.

> @@ +638,5 @@
> > +       let coverage = script.getOffsetsCoverage();
> > +       if (!coverage) return;
> > +
> > +       coverage.forEach((data, i) => {
> > +         hitcounts[data.lineNumber] = Math.max(hitcounts[data.lineNumber] || 0, data.count);
> 
> Are you sure this is correct? I would assume that the script has the number
> of times itself has been hit, so you should take the max of all the scripts
> on the same line, you should add them together.

The problem here, is that the code coverage report is made on a bytecode-offset basis and not on a line-offset basis.  Doing a sum, might produce confusing outputs such as:

50    var a = foo();
150   var b = a ? 1 : 0;

The reason being that the "?:" will appear as multiple bytecode instructions which are sharing the same line.
Comment on attachment 8817588 [details] [diff] [review]
cov2.patch

Review of attachment 8817588 [details] [diff] [review]:
-----------------------------------------------------------------

::: devtools/server/actors/source.js
@@ +643,5 @@
> +       });
> +     });
> +
> +     return Object.keys(hitcounts).map(key => ({
> +       line: +key,

Any reason not to use an array indexed by line numbers?
Attachment #8817588 - Flags: feedback+
Flags: needinfo?(nicolas.b.pierron)
Product: Firefox → DevTools
Priority: P2 → P4
Type: defect → enhancement
Priority: P4 → P5
Blocks: dbg-server
Assignee: jlaster → nobody
Status: ASSIGNED → NEW
Severity: normal → S3
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: