Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

I searched a bit, but didn't find anything particularly pertinent to my problem - so please do excuse me if I missed something!

A few months back I inherited the source to a fairly-popular indie game project and have been working, along with another developer, on the code-base. We recently made our first release since taking over the development but we're a little stuck.

A few users are experiencing slowdowns/lagging in the current version, as compared to the previous version, and we are not able to reproduce these issues in any of our various development environments (debug, release, different OSes, different machines, etc.). What I'd like to know is how can we go about implementing some form of logging/debugging mechanism into the game, that users can enable and send the reports to us for examination? We're not able to distribute debug binaries using the MSVS 2010 runtimes, due to the licensing - and wouldn't want to, for a variety of reasons.

We'd really like to get to the bottom of this issue, even if just to find out it's nothing to do with our code base but everything to do with their system configuration. At the moment, we just have no leads - and the community isn't a very technically-savvy one, so we're unable to rely on 'expert' bug reports or investigations.

I've seen the debug logging mechanism used in other applications and games for everything from logging simple errors to crash dumps. We're really at a loss at this stage as to how to address these issues, having been over every commit to the repository from the previous to the current version and not finding any real issues.

share|improve this question

1 Answer 1

up vote 7 down vote accepted

It sounds like you really want to implement some kind of deployed profiling option, not logging in general (while you could use logging to surface the results of your profile data, logging in general isn't really required here because there are better ways to surface the data).

The basic premise will be to have some fairly lightweight methods/objects you can call or create in your code to track timestamps and shove them into data structure, which you then serialize to disk in some form so that users can email it to you. Something like a BeginTask and EndTask function that takes some kind of task identifier -- a string, or number, or whatever. When BeginTask is called, you can record the current time via a high-resolution counter and store it. Then you do the same in EndTask, except you look for the matching BeginTask timestamp and compute the difference, giving you a task duration.

You can store these in a tree-like structure to give yourself hierarchical profiling (which will help alleviate the issue of coming up with unique task names to match up begin/end pairs). You can also take advantages of C++ idioms such as RAII by putting the calls into the constructor/destructor of some Profile class, then you can simply construct one of these Profile instances in every function that might be time-critical and you'll get the begin/end calls automatically.

You can go even further than that an enable penter and pexit hooks to call your profiler functions for every function in your code automatically, which is a lot less painful than retrofitting construction of Profiler objects everywhere. It will also catch things you might have decided "couldn't be slow" and thus avoided adding Profiler objects to. Unfortunately it's a bit more work to write proper penter/pexit hooks.

Then you can save this information to disk. You could just dump it to a plain-text log file, for simplicity. I find that it's much better to dump the data into a binary format that you can parse back later with a tool on your end -- but if you're not up for writing such a tool, plain text will serve in a pinch. You'll still probably want some code to scan through the data and find the tasks that took the longest and print them outside of the regular call hierarchy, because that's what you're most likely interested in.

Once you have this functionality enabled, you can have users send you their profiling logs and you can hopefully use that to see what is taking up too much time on their machines, and that might help guide your optimization efforts.

We do this kind of instrumentation on our content production tools at work, and dump the statistics into a database which we use to develop daily metrics reports about task performance. Tasks that become outliers in terms of runtime, or take too long on average (especially if they're running on the UI thread) are hilighted in these reports so we know when we accidentally hurt the performance of something.

share|improve this answer
    
Many thanks for your detailed answer but pardon me for being exceptionally stupid: how does this help in terms of defining where the problem is? If using penter/pexit hooks, how am I going to determine the calling function? Surely the IP is relative to the individual execution and I'm not aware of a method to get the calling function name. I thought I could probably write macros that pass __FUNCTION__ along, but that completely defeats the object of using penter/pexit, as it's high-maintenance and needs to be done for each function. Please do pardon my lack of experience in this area :) –  James Burgess Mar 6 '11 at 8:47
    
There's a StackWalk64 API call you can make to get information about calling functions, et cetera: msdn.microsoft.com/en-us/library/ms680650(v=vs.85).aspx –  Josh Petrie Mar 6 '11 at 18:45
    
Seems very useful - thanks for your help :) –  James Burgess Mar 8 '11 at 7:37

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.