Wednesday, February 09, 2005

It's egg on face time

I'm here in Texas to solve a major performance problem in our software. It surfaced in France but I was unable to troubleshoot it there; the customer wants our hardware working 24/7 and that's not really compatible with the kinds of things you need to do to solve performance problems.

If you've followed this blog (or read back) you'll know that I inherited this app and moreover you'll know that I don't think it's all that well written. Thus it was that I fell into the classic arrogance trap. After all, we're using the app in a way that differs in subtle ways from previous practice. So if we hit performance problems when using the app differently it has to be a problem with the architecture of the app or the way the old code was written, right?

Wrong! It was a bug in new code I wrote.

Buggy code.
// Calculate the average temperature for the oven
for (i = 1; it != m_vOven.end(); i++)
{
fTemp += (*it)->GetAvgTemp();
fTemp /= i;
}
code without the bug
// Calculate the average temperature for the oven
for (i = 1; it != m_vOven.end(); i++, it++)
{
fTemp += (*it)->GetAvgTemp();
fTemp /= i;
}
uh huh. I'm using an std iterator across a std vector. As long as the iterator isn't equal to the end of the vector stay in the loop. Well you're going to stay in that loop forever if you don't increment the damn iterator! This code was inside a thread that's supposed to check the temperature once per minute. As originally written it sits at 100% CPU and starves all other processes on the machine of CPU. The fixed version exits the loop very quickly and the process sits at an average of 2% CPU. Quite a difference!

No comments: