ay n om Create a tempo from the char pointer retumed bya( 。Destroy all three s+ri from the ebug (call So we go to all this trouble to construct three temporarystng objects,and proceed to drop them all over the floor when w out that trace is ctive.The overhead of creating and de stroying those ould easily hed figment of our imagination.We have ac ctually e rienced it in a real oryofanatcnproadacgcanctodeteinto ofa half million lines of C++code.Our first attempt backfired due to atrocious performance. Our Initial Trace Implementation int myFunction(int x) "myFunction" string moreInfo -"more interesting info"; debug (moreInfo) );//Trace destructor logs exit event to an output stream To enable this usage we started out with the following implementation class Trace public ce (const string sname); Hebug (const string smsg) string theFunctionName; ) The Trace constructor stores the function's name. :ace(cons ring)thePunctionlame (nAme) if (TraceIsActive)( cout <"Enter function"<<name <endli Additional information messages are logged via calls to the debug (method. 2 • Create a temporary string object from "x = " • Call itoa(x) • Create a temporary string object from the char pointer returned by itoa() • Concatenate the preceding string objects to create a third temporary string • Destroy all three string temporaries after returning from the debug() call So we go to all this trouble to construct three temporary string objects, and proceed to drop them all over the floor when we find out that trace is inactive. The overhead of creating and destroying those string and Trace objects is at best hundreds of instructions. In typical OO code where functions are short and call frequencies are high, trace overhead could easily degrade performance by an order of magnitude. This is not a farfetched figment of our imagination. We have actually experienced it in a reallife product implementation. It is an educational experience to delve into this particular horror story in more detail. It is the story of an attempt to add tracing capability to a complex product consisting of a halfmillion lines of C++ code. Our first attempt backfired due to atrocious performance. Our Initial Trace Implementation Our intent was to have the trace object log event messages such as entering a function, leaving a function, and possibly other information of interest between those two events. int myFunction(int x) { string name = "myFunction"; Trace t(name); ... string moreInfo = "more interesting info"; t.debug(moreInfo); ... }; // Trace destructor logs exit event to an output stream To enable this usage we started out with the following Trace implementation: class Trace { public: Trace (const string &name); ~Trace (); void debug (const string &msg); static bool traceIsActive; private: string theFunctionName; }; The Trace constructor stores the function's name. inline Trace::Trace(const string &name) : theFunctionName(name) { if (TraceIsActive) { cout << "Enter function" << name << endl; } } Additional information messages are logged via calls to the debug() method