Boost logo

Boost :

From: christopher diggins (cdiggins_at_[hidden])
Date: 2005-02-11 20:14:25


Christopher Diggins
Object Oriented Template Library (OOTL)
http://www.ootl.org
----- Original Message -----
From: "Preston A. Elder" <prez_at_[hidden]>
To: <boost_at_[hidden]>
Sent: Friday, February 11, 2005 4:34 PM
Subject: [boost] Re: Re: Profiling Library suggestion

> Hum
>
> I don't know why, but my last e-mail on this subject went AWOL, so I'm
> going to re-type it (which is a shame, as it was quite long).

:(

> I think the profiler is making great progress, however I still have two
> major issues with it.

Thanks.

> First, that the policy stuff is all static. This makes it impossible for
> me to have two or more individual profilers going, using the same policy,
> but, say, a different output file, without making the policy extremely
> complex and doing all kinds of string matching to sort out whats what.

How would you propose doing it differently?

In the latest version You can now use meta-data to associate extra tags with
data to help for generating different reports. Consider the code at
http://www.cdiggins.com/profiler/v2/custom_profile_manager.hpp , one can
introduce a new field into meta_profile_data, which would hopefully be
satisfactory for grouping profiles?

> I want the 'huge', 'big' and 'small' profile instances to use different
> collectors that all use the same policy (accumulate and count, plus print
> to file every, say, 30s), but, say, output to different files. With the
> static nature of everything you have in there regarding this, I would need
> to either:
> a) create a separate policy just to change the output file.

Would this be so bad?

> or b) in the policy, some how determine which named entries go to which
> accumulator, and then record as such.

And now c) add extra metadata and switch on it.

> Having them separate would allow me to disable them separately, too.

One solution for disabling groups of profiles is to define multiple profile
managers for the different profile groups:

struct huge_profile_manager : default_profile_manager { }
struct big_profile_manager : default_profile_manager { }
struct small_profile_manager : default_profile_manager { }

profiler<huge_profile_manager> p1;
profiler<big_profile_manager> p2;
profiler<small_profile_manager> p3;

// turn off only big_profiles
template<> struct profiler<big_profile_manager> : empty_profiler { };

(note: empty_profiler doesn't exist yet, but I will add it).

> For
> example, I could use the 'huge' to get a general idea of what section of
> code on average takes the longest. Then I could drill down slightly
> further to find out which portion of that code is taking the longest, and
> then even further to find out which particular options are taking longest,
> and I could do it all individually.
>
> Second is the syntax, which requires me to either declare all profiled
> sections ahead of time, pause them, then when I get to the part I want
> resume and pause them again, or use ugly scoping syntax to encapsulate
> multiple blocks of code.
>
> For an example of the first, assume in the MyFunc I want every opX_*
> call profiled as one. The goal here is to find out, over calls to MyFunc,
> how much time opX_* is taking, not how many times opX_* is called and the
> average time for that call. Like so:
>
> void MyFunc()
> {
> Profile p_op1("op1"), p_op2("op2"), p_op3("op3");
> p_op1.pause();
> p_op2.pause();
> p_op3.pause();
>
> for (i=0; i<100; ++i)
> {
> p_op1.resume();
> op1_part1();
> op1_part2();
> p_op1.pause();
>
> p_op2.resume();
> op2_part1();
> op2_part2();
> p_op2.pause();
>
> p_op3.resume();
> op3_part1();
> op3_part2();
> p_op3.pause();
> }
>
> do_something();
>
> for (i=0; i<100; ++i)
> {
> p_op1.resume();
> op1_part1();
> op1_part2();
> p_op1.pause();
>
> p_op2.resume();
> op2_part1();
> op2_part2();
> p_op2.pause();
>
> p_op3.resume();
> op3_part1();
> op3_part2();
> p_op3.pause();
> }
> }
>
> This is the only way to get all opX_* functions accumulated together, so
> that the count goes up by 1 for each call to MyFunc, and the time for all
> instances of opX_* is added, as opposed to getting a 200 count opX_*
> function calls, and then the averaging being the time per call (which is
> not what I want in this case).

Why is this code so bad and what is the alternative?

> For an example of the second, try this:
>
> void MyFunc()
> {
> {
> Profile op1("op1");
> op1_part1();
> int rv1 = op1_part2();
> }
>
> {
> Profile op2("op2");
> op2_part1();
> op2_part2();
> }
>
> if (rv > 30)

rv is not accessible here.

> Profile::generate_report();
>
> {
> Profile op1("op1");
> op1_part1();
> op1_part2();
> }
> }
>
> Obviously, in the example, I want the profiling data done before the
> report generate in the report generated. And the stuff afterwards not.
> So I can't, as in the previous example, declare it at the beginning.
> Either way, the scoping operators used here are kind of ugly.

I don't follow your intent here sorry.

Thanks for your feedback,
CD


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk