Paul Johnson
2012-09-07 14:31:29 UTC
In accordance with the terms of my grant from TPF this is the report for
week 12 of my work on improving Devel::Cover.
This report covers 04.08 to 10.08.
If you remember last week's cliffhanger (yes, it was actually a month
ago) you'll recall that based on a seemingly unrelated RT ticket I was
on the tracks of a longstanding problem which had hitherto evaded me by
dint of my never being able to pull together sufficient time to track it
down. Thanks to this grant I was able to spend the time necessary to
locate and fix the problem.
As is often the case, all the work was in finding the problem. Once
found, the solutions was all but trivial.
The problem was in the heart of probably the most complicated part of
Devel::Cover. That is the code which tries to manage the dynamic nature
of Perl.
Code coverage in a static language such as C is relatively
straightforward. Source code is compiled to object code and that object
code doesn't change. (Self-modifying code is an illusion. It doesn't
exist.) Everything you need to know about the code is known before a
line of it has been executed.
In Perl, and similar languages, the separation of compile time and run
time is not so clear cut. Code being executed can get perl to compile
new code into already existing modules. This poses challenges to a tool
such as Devel::Cover which tries to collect information about the code
being executed.
If you consider just subroutine coverage, in "normal", static code, I
can note the subroutines in a file and produce a mapping from the
subroutines to the position in the source code where they are defined,
producing an ordering on the subroutines. When a subroutine is executed
I can note that the nth subroutine in the file is covered.
In dynamic code new subroutines can spring into existence whilst the
code is being executed. This happens via a string eval in some guise.
When this happens I can tag the new sub onto the end of my list of subs,
and this works well.
But the problem becomes more difficult when in two different runs,
different subroutines are created. A naïve solution here can lead to
subroutine $n meaning different subroutines in different runs. So we
need to be clever and recognise when one of these new subroutines
matches an identical subroutine from a previous run, and when it has
never been seen before.
If all this functions correctly we should never get to a situation where
we have information that subroutine $n has been executed, but we only
know about n-1 subroutines. If that situation does occur, we get the
"ignoring extra subroutine" message and coverage will be lost.
The bug existed in the code which managed how these lists of criteria
were maintained between runs. There may still be bugs in this area, but
it was great to be able to knock this one over. The actual commit was
https://github.com/pjcj/Devel--Cover/commit/997426eecb16899d0be425853478e2b5bdf9a1ee
if you want to see the simple fix to the hard-to-find provlem.
I should probably note that there are other solutions to this problem.
Early versions of Devel::Cover stored the location of each construct
together with the information about its coverage. This does work well
but is very expensive on storage requirements and the CPU required
manage this extra data. Coverage always has an overhead and the greater
the overhead the less people will be inclined to use it, so I try hard
to keep the overhead to a minimum.
Whilst tracking down and fixing this problem I also fixed more than ten
other bits and bobs that I noticed, as well as other peripheral matters.
The full details are in the commits. A couple of those bits and bobs
are probably quite important, actually.
Oh, And then I did fix up the remainder of the problem in the original
bug report.
I also got a message from Nuno Carvalho who is packaging Devel::Cover
for Debian. It seems that PodVersion isn't happy when the module
description is longer than one line. Since that's not a very good idea
anyway I fixed up the affected modules so with luck the Debian packaging
can go ahead.
Closed RT tickets:
68517 summary, report total from cover tool includes ignored files
77818 tests fail due to spaces in @INC (Devel::Cover::Inc issue)
You can see the commits at https://github.com/pjcj/Devel--Cover/commits/master
Hours worked:
04.08 14:00
07.08 1.55
09.08 2:20
Total 18:15
week 12 of my work on improving Devel::Cover.
This report covers 04.08 to 10.08.
If you remember last week's cliffhanger (yes, it was actually a month
ago) you'll recall that based on a seemingly unrelated RT ticket I was
on the tracks of a longstanding problem which had hitherto evaded me by
dint of my never being able to pull together sufficient time to track it
down. Thanks to this grant I was able to spend the time necessary to
locate and fix the problem.
As is often the case, all the work was in finding the problem. Once
found, the solutions was all but trivial.
The problem was in the heart of probably the most complicated part of
Devel::Cover. That is the code which tries to manage the dynamic nature
of Perl.
Code coverage in a static language such as C is relatively
straightforward. Source code is compiled to object code and that object
code doesn't change. (Self-modifying code is an illusion. It doesn't
exist.) Everything you need to know about the code is known before a
line of it has been executed.
In Perl, and similar languages, the separation of compile time and run
time is not so clear cut. Code being executed can get perl to compile
new code into already existing modules. This poses challenges to a tool
such as Devel::Cover which tries to collect information about the code
being executed.
If you consider just subroutine coverage, in "normal", static code, I
can note the subroutines in a file and produce a mapping from the
subroutines to the position in the source code where they are defined,
producing an ordering on the subroutines. When a subroutine is executed
I can note that the nth subroutine in the file is covered.
In dynamic code new subroutines can spring into existence whilst the
code is being executed. This happens via a string eval in some guise.
When this happens I can tag the new sub onto the end of my list of subs,
and this works well.
But the problem becomes more difficult when in two different runs,
different subroutines are created. A naïve solution here can lead to
subroutine $n meaning different subroutines in different runs. So we
need to be clever and recognise when one of these new subroutines
matches an identical subroutine from a previous run, and when it has
never been seen before.
If all this functions correctly we should never get to a situation where
we have information that subroutine $n has been executed, but we only
know about n-1 subroutines. If that situation does occur, we get the
"ignoring extra subroutine" message and coverage will be lost.
The bug existed in the code which managed how these lists of criteria
were maintained between runs. There may still be bugs in this area, but
it was great to be able to knock this one over. The actual commit was
https://github.com/pjcj/Devel--Cover/commit/997426eecb16899d0be425853478e2b5bdf9a1ee
if you want to see the simple fix to the hard-to-find provlem.
I should probably note that there are other solutions to this problem.
Early versions of Devel::Cover stored the location of each construct
together with the information about its coverage. This does work well
but is very expensive on storage requirements and the CPU required
manage this extra data. Coverage always has an overhead and the greater
the overhead the less people will be inclined to use it, so I try hard
to keep the overhead to a minimum.
Whilst tracking down and fixing this problem I also fixed more than ten
other bits and bobs that I noticed, as well as other peripheral matters.
The full details are in the commits. A couple of those bits and bobs
are probably quite important, actually.
Oh, And then I did fix up the remainder of the problem in the original
bug report.
I also got a message from Nuno Carvalho who is packaging Devel::Cover
for Debian. It seems that PodVersion isn't happy when the module
description is longer than one line. Since that's not a very good idea
anyway I fixed up the affected modules so with luck the Debian packaging
can go ahead.
Closed RT tickets:
68517 summary, report total from cover tool includes ignored files
77818 tests fail due to spaces in @INC (Devel::Cover::Inc issue)
You can see the commits at https://github.com/pjcj/Devel--Cover/commits/master
Hours worked:
04.08 14:00
07.08 1.55
09.08 2:20
Total 18:15
--
Paul Johnson - ***@pjcj.net
http://www.pjcj.net
Paul Johnson - ***@pjcj.net
http://www.pjcj.net