tags:

views:

151

answers:

7

Keeping track of how many times a function is called is easy when passing the counter as an argument into the function. It's also easy when returning a one from the called function. But, I do not want to go that route. The reason behind this is because it seems like bad programming (letting the function know too much information). Is there a better way to keep track of how many times this function has been called?

I'm just looking for concepts that I could study. Providing code examples is not neccessary, but might be helpful.

Edit: I'm not actually looking for profiling tools. Let me add some code to get my point across. Because scope for funcCounter ends in main, I have no way of getting back a variable from myFunction that will increment funcCounter. I could possibly return 1 from myFunction and then increment funcCounter that way, but this doesn't seem like very good programming. Is there another way to do it?

int main()
{
int funcCounter = 0;
char *mystring = "This is a silly function.";
myFunction(mystring);
cout << "Times function is called: " << funcCounter << endl;
    return 0;
}

void myFunction(char *mystring)
{
cout << mystring << endl;
}
+2  A: 

Bad coding style, but maybe a global variables and if necessary mutex locks may do the trick.

Joshua Moore
+4  A: 

I would do this through the use of a profiling tool like gcov (which is for linux). These programs do the work of inserting code into your program during compilation and give you a report of how many times a function is called, where its called from, and how long the program spent executing that function.

Joe
+3  A: 

It sounds like what you are looking for is a profiler. Depending on the platform you are using there are a slew of tools available that can help you hunt down the (ab)uses of a routine.

Please revise your question with the platform for which you need profiling tools.

fbrereto
This bothers me a lot. A lot of very knowledgeable people seem to that answer a question based on what they think the question is about (as opposed to what was actually asked). There are many times that you guys are indeed correct, however there are times in which you totally wrong and in the end your answer is useless (despite it being up voted by dozens of people). Answer the question as stated and if you have something else to add, then add it after you've answered the original question. I apologize, I'm in a bad mood today, please forgive my outburst.
Faken
Completely forgiven. I myself have been forgiven of far, far greater.
fbrereto
+12  A: 

Have a static variable in your function and keep incrementing it each time the function in called.

void my_Function(void) {
    static unsigned int call_count = 0;
    call_count++;
}

If you want to do it for debugging reasons, then there are tools like gcov which do this for you. (I'm pretty sure Microsoft doesn't have an alternative bundled with Microsoft Visual C++)

Aviral Dasgupta
What use is a static local? You have to either print it out from inside the function under test or access it with a debugger. Seems pretty pointless to me....
SoapBox
@SoapBox : Yep, that's what you do.
Aviral Dasgupta
Note that this isn't thread safe.
Stephen
+3  A: 

If the function is part of a class, you can add a static counter to the class, plus an accessor and/or reset functions:

class X
{
private:
    /* diagnostics */
    static int counter = 0;
    int read_counter() const { return counter; }
    void reset_counter() { counter = 0; }

public:
    /* real code */
    fcn() {
        ++counter;
        /* ... */
    }
};

The problem with adding a static counter to a standalone function is that there's no way to get at the value.

You could add a global, of course, but instead of a raw global I'd suggest an instance of a singleton containing all your diagnostic code and data.

egrunin
+3  A: 

Use a class like this one, and simply instantiate it at the top of a function (or any other block) like is done in f() below.

Note: There is some overhead for gettimeofday() so you may want to use a different timing method, but that is a completely different topic worthy of it's own question (and has been addressed before on SO).

#include <iostream>
#include <string>
#include <map>
#include <sstream>
#include <ctime>
#include <cstdlib>
#include <sys/time.h>

class PerfStats 
{
private:
    std::string which_;
    timeval begin_;

public:

    PerfStats(std::string const &file, int line)
    {
        std::stringstream ss;
        ss << file << ':' << line;
        which_ = ss.str();
        gettimeofday(&begin_, NULL);
    }

    ~PerfStats()
    {
        timeval end;

        gettimeofday(&end, NULL);

        Times[which_] = (end.tv_sec - begin_.tv_sec) + (end.tv_usec - begin_.tv_usec)/1000000.0;
        ++Counts[which_];
    }

    static std::map<std::string, double> Times;
    static std::map<std::string, unsigned int> Counts;

    static void Print()
    {
        for(std::map<std::string, double>::iterator it = Times.begin(); it != Times.end(); ++it)
            std::cout << it->first << " :\t" << it->second << "s" << std::endl;

        for(std::map<std::string, unsigned int>::iterator it = Counts.begin(); it != Counts.end(); ++it)
            std::cout << it->first << " :\t" << it->second << " times" << std::endl;
    }
};


std::map<std::string, double> PerfStats::Times;
std::map<std::string, unsigned int> PerfStats::Counts;

void f()
{
    PerfStats(__FILE__, __LINE__);
    usleep(1);
}

main()
{
    srand(time(NULL));

    for(int i = 0; i < rand(); ++i)
        f();
    PerfStats::Print();
}

Sample output:

test.cpp:54 :   2e-06s
test.cpp:54 :   21639 times
SoapBox
A: 

Thanks everyone. I ended up using the "static" keyword on the counter inside the function I needed to keep track of and this worked beautifully.

Brundle
Then you should accept that answer as the best one...
Ivar Bonsaksen