Reputation: 5509
I have never done profiling. Yesterday I programmed a ProfilingTimer class with a static timetable (a map<std::string, long long>) for time storage.
The constructor stores the starting tick, and the destructor calulates the elapsed time and adds it to the map:
ProfilingTimer::ProfilingTimer(std::string name)
: mLocalNameLength(name.length())
{
sNestedName += name;
sNestedName += " > ";
mStartTick = Platform::GetTimerTicks();
}
ProfilingTimer::~ProfilingTimer()
{
long long totalTicks = Platform::GetTimerTicks() - mStartTick;
sTimetable[sNestedName] += totalTicks;
sNestedName.erase(sNestedName.length() - mLocalNameLength - 3);
}
In every function (or {block}) that I want to profile i need to add:
ProfilingTimer _ProfilingTimer("identifier");
This Profiling work all fine when I build a release version from Visual C++ 2010 Professional. But when I build as Debug I get a huge fps drop (from 63 down to ~20).
These are the numbers I get when I print my timetable (Debug build):
Update() > Tower::Update > : 2551 ms (84100m%)
Update() > Tower::Update > Tower::Update1 > : 1313 ms (43284m%)
Update() > Tower::Update > Tower::Update1 > Tower::FindNewTarget > : 6 ms (204m%)
Update() > Tower::Update > Tower::Update1 > Tower::HasTargetInRange > : 5 ms (184m%)
Update() > Tower::Update > Tower::Update2 > : 659 ms (21756m%)
Update() > Tower::Update > Tower::Update2 > Tower::HasTargetInRange > : 5 ms (187m%)
Update1 and Update2 times the first and second half respectively of Update. Why doesnt they add up to 84,1 %?
Still this 84% is a huge number - in release build I get this output:
Update() > : 770 ms (1549m%)
Update() > Tower::Update > : 722 ms (1452m%)
Update() > Tower::Update > Tower::FindNewTarget > : 44 ms (89m%)
Update() > Tower::Update > Tower::HasTargetInRange > : 92 ms (187m%)
1,4% instead of 84,1%. That is a huge difference!
Anyone knows why?
EDIT: I guess release is much faster than Debug, but why is this profiling so time consuming? Is std::map the time hogger or am I doing something extremely wrong?
EDIT: Updated the code. The initiation wasn't needed, and now stores the length of mLocalName instead of the actual string.
Upvotes: 4
Views: 613
Reputation: 17978
There are a couple performance issues with your code.
mLocalName
even exist? Just refer to name
directly.unordered_map
available for your use.Instead of doing sTimetable[sNestedName] = 0;
, use the iterator you already retrieved.
Timetable::iterator loc = sTimetable.find(sNestedName);
if(loc == sTimetable.end())
sTimetable[sNestedName] = 0;
Addendum: Visual Studio comes with a profiler last I checked. Why not just use that?
Upvotes: 2
Reputation: 229794
Using long strings as an index into a std::map
is probably not the fastest way to do this. Long strings with common beginnings mean that each time you compare two of these strings, a lot of characters have to be looked at to see if the strings are equal or not. std::map
is basically a binary tree and does O(log(n)) comparisons on each lookup/insert. Using shorter or numeric keys should speed up all the map operations.
Also, using std::unordered_map
might (or might not) improve speed, depending on how many elements the map contains and what kind of keys are used.
In the profiling class, the constructor should take the name as a reference to avoid creating an unnecessary copy of that string:
ProfilingTimer::ProfilingTimer(const std::string &name)
Generally avoiding unnecessary copies is a good idea. For example, you maybe don't really need the mLocalName
member and it could be enough to just store the string length instead.
The profiling functions are probably called very often, so small delays can add up over the run of the program.
Upvotes: 2
Reputation: 35980
Microsoft adds a lot of safety checking to their container libraries in debug mode. This is beneficial. You'd rather catch out of bounds exceptions and the like in functions such as vector::operator[]
instead of deciphering memory corruptions (would still recommend calling vector::at
.) However, there's also a ton of other things that go into inserting debugger hooks that impact your code and it's performance.
Upvotes: 2