in reply to Re: Fast coverage module or hack
in thread Fast coverage module or hack

First idea - no. we use "use" and compile time to load all stuff before "fork" webserver and to save memory with COW, so every module "use" maybe 80% of other modules.

Second idea - yes we already do this. We run map collection once per day (before Devel::Cover is so slow for us). But when map changes, it actually can break things for rest of day. So we run map collection once per day, but also do git-diff to the commit where map collection was made, then there is no possibility of use of wrong map then, but diff gets bigger during the day. So we're looking how to speed up coverage module.

Replies are listed 'Best First'.
Re^3: Fast coverage module or hack
by tobyink (Canon) on Dec 02, 2019 at 12:29 UTC

    How slow are we talking about? 10 minutes? An hour? 6 hours?

    Would doing the Devel::Cover run overnight instead of the day help?

      I think about 4 hours (run without devel cover is 40 mins). It can be run overnight, but any way it better to be run as often, as possible. Otherwise data not accurate.

      I am looking for alternative now. https://metacpan.org/pod/Devel::Trace (If I change printing lines to tracking lines) looks good.
Re^3: Fast coverage module or hack
by tobyink (Canon) on Dec 02, 2019 at 12:39 UTC

    I think I have an idea for a solution but it would require a one-line change (a use statement added) to each module. Does that sound acceptable?

    My solution will need me to do a little work to figure out the details, but it seems like an interesting task to work on, and it might help me with one or two of my own projects.

    Edit: actually probably don't need a change to each module.

    Edit again: actually do.

      Does that sound acceptable?
      yes, it does. there can be a script which automatically add/replace lines in source files before test run.

        I will probably put this on CPAN soonish, but here's the gist of it. Below is the contents of "Devel::TraceCalls". Most of its dependencies are in core, except for Hook::AfterRuntime and match::simple which are on CPAN.

        You need to use Devel::TraceCalls in each module.

        Devel::TraceCalls does three things:

        1. Checks the PERL_TRACE_CALLS environment variable is true. If it's false, it doesn't do the next two things.

        2. Wraps every sub in the caller module with tracking code to count how many times the sub has been called. This wrapper uses goto to call the original sub, so it should be invisible to caller. It does wrap imported subs, so if you don't want them wrapped, clean then with namespace::autoclean. It does wrap generated subs, like Moose attributes. It doesn't wrap inherited subs. (Though of course the class you're inheriting from can use Devel::TraceCalls). Note that Moose constructors are inherited if your class is mutable and generated if your class is immutable.

        3. In an END { ... } block, it uses FindBin to find the name of the test script, and creates a JSON file with the same name but a ".t.map" file extension. In this JSON file, it dumps a hashref where the keys are the modules which have been called.

        The end result is that if you run:

        PERL_TRACE_CALLS=1 prove -l t/sometest.t

        You'll get a file called "t/sometest.t.map" containing something like this:

        { "Local::Example" : { "quux" : 1 }, "Local::Example::Module1" : { "bar" : 1 }, "Local::Example::Module2" : { "bar" : 1, "foo" : 1 } }

        There are some deliberate optimizations like loading dependencies in a stringy eval, so even if you do use Devel::TraceCalls in production code, it shouldn't waste time or memory.