6

I'm currently working on a scientific computing project involving huge data and complex algorithms, so I need to do a lot of code profiling. I'm currently relying on <ctime> and clock_t to time the execution of my code. I'm perfectly happy with this solution... except that I'm basically timing everything and thus for every line of real code I have to call start_time_function123 = clock(), end_time_function123 = clock() and cout << "function123 execution time: " << (end_time_function123-start_time_function123) / CLOCKS_PER_SEC << endl. This leads to heavy code bloating and quickly makes my code unreadable. How would you deal with that?

The only solution I can think of would be to find an IDE allowing me to mark portions of my code (at different locations, even in different files) and to toggle hide/show all marked code with one button. This would allow me to hide the part of my code related to profiling most of the time and display it only whenever I want to.

Adrien
  • 324
  • 1
  • 3
  • 10
  • You could make a start and end function using said code and just call them when needed. – Nick Pavini Feb 25 '17 at 15:11
  • 2
    You should look into [std::chrono](http://en.cppreference.com/w/cpp/chrono). – Jesper Juhl Feb 25 '17 at 15:14
  • How does std::chrono answers my question? – Adrien Feb 25 '17 at 15:20
  • @Adrien I'm not answering your question. I posted a *comment* not an *answer*. I'm just giving you a recommendation for something you should research in order to use something better than `ctime`. – Jesper Juhl Feb 25 '17 at 15:24
  • @NickPavini Sure I could make it a little less lengthy but that's not the main issue. I don't want to write/erase or even comment/uncomment each individual timing code line each time I change something and want to test things. I'm currently using a system based on additional verbosity flags arguments in my function to decide if it should print timings or not. What I want is to not have half of my written code being about timings. – Adrien Feb 25 '17 at 15:29
  • @JesperJuhl Ok, sorry! But I don't see how telling me to look into a library without any explanation helps me. What I know is is about high precision (which I don't need, since my execution times are not small) while guarantees that it measures program time and not system time (which is important to me). – Adrien Feb 25 '17 at 15:37
  • 2
    What operating system? What compiler & version? Can't you use profiling facilities (like [gprof(1)](http://man7.org/linux/man-pages/man1/gprof.1.html) or `oprofile` ?) On Linux read *carefully* [time(7)](http://man7.org/linux/man-pages/man7/time.7.html) – Basile Starynkevitch Feb 25 '17 at 16:23
  • 1
    Instead of manually instrumenting your source for profiling, you should invest in a tool. – Eugene Feb 25 '17 at 16:23

2 Answers2

7

Have a RAII type that marks code as timed.

struct timed {
  char const* name;
  clock_t start;
  timed( char const* name_to_record):
    name(name_to_record),
    start(clock())
  {}
  ~timed(){
    auto end=clock();
    std::cout << name << " execution time: " << (end-start) / CLOCKS_PER_SEC << std::endl;
  }
};

The use it:

void foo(){
  timed timer(__func__);
  // code
}

Far less noise.

You can augment with non-scope based finish operations. When doing heavy profiling sometimes I like to include unique ids. Using cout esoecially with endl could result in it dominating timing; fast recording to a large buffer that is dumped out in an async manner may be optimal. If you need to time ms level time, even allocation, locks and string manipulation should be avoided.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
1

You don't say so explicitly, but I assume you are looking for possible speedups - ways to reduce the time it takes.

You think you need to do this by measuring how much time different parts of it take. If you're interested, there's an orthogonal way to approach it.

Just get it running under a debugger (using a non-optimized debug build). Manually interrupt it at random, by Ctrl-C, Ctrl-Break, or the IDE's "pause" button. Display the call stack and carefully examine what the program is doing, at all levels.

Do this with a suspicion that whatever it's doing could be something wasteful that you could find a better way to do.

Then if you start it up again, and halt it again, and see it doing the same thing or something similar, you know you will get a substantial speedup if you fix it. The fewer samples you took to see that thing twice, the more speedup you will get.

That's the random pausing technique, and the statistical rationale is here. The reason you do it on a debug build is here. After you've cut out the fat using this method, you can switch to an optimized build and get the extra margin it gives you.

Community
  • 1
  • 1
Mike Dunlavey
  • 40,059
  • 14
  • 91
  • 135
  • 1
    Thanks a lot, that's very interesting! However I don't agree with the idea of profiling in debug mode: I want to be optimizing only the bottleneck of my code, and the speed-up factor provided by release mode/optimization flags is definitely not the same for all parts of the program, so how does profiling in debug mode help me find what the bottleneck of my code is? – Adrien Feb 25 '17 at 17:53
  • @Adrien: because as that link explains, the optimizer can only speed things up that are at the bottom of the call stack, and only if they are in non-library code that the compiler actually sees. It can optimize things higher up, but the program counter spends little time there. What it can do is make it difficult to find the speedups only *you* can fix, such as unnecessary memory allocation, functions in need of memoizing, functions in need of special-casing, etc. etc. – Mike Dunlavey Feb 25 '17 at 17:59