Path: utzoo!censor!geac!torsqnt!news-server.csri.toronto.edu!bonnie.concordia.ca!uunet!tut.cis.ohio-state.edu!att!att!westmark!mole-end!mat From: mat@mole-end.UUCP (Mark A Terribile) Newsgroups: comp.lang.c++ Subject: Re: why is this program slow? Summary: Constructors and returns Message-ID: <467@mole-end.UUCP> Date: 11 Jan 91 09:15:25 GMT References: <1991Jan9.002244.23398@news.cs.indiana.edu> <14167@ulysses.att.com> Organization: mole-end--private system. admin: mole-end!newtnews Lines: 72 > > I have a C++ program that takes about 170% as long as a similar C program. > > ... I don't understand the slowdown. > The C program is written in terms of basic operations that the optimizer > can easily improve; the C++ version isn't. For example: > > a[0] = a[0] + b[0]; > This is better written as > a[0] += b[0]; > though modern compilers can usually make the two cases equivalent. The > C++ version is not so fortunate. You write > > a = a + b; > Since `a' is a structure, your `+' operator first has to store the sum in > your `temp', then your `=' operator must copy it into `a'. This takes a > string move at best, and a slow function call at worst. I tried redefining > your `+' operator to be a `vector& +=' operator and my execution time on > a tahoe became 6.0 seconds instead of 14.5. That's still not quite as > good as 4.5 for the C version, but it explains most of the difference. There's also some genuinely bad use of C++ initialization rules around returns and parameters. Fixing it won't make the problem go away, but it will probably shave about half off the extra cost. In the operator+() , you force the loading of a temporary vector, then a copy from the temporary to the return value. Sometimes this is unavoidable; here it is not. Instead of writing inline vector operator+(vector& u, vector& v) { vector temp; temp.data[0] = u.data[0] + v.data[0]; temp.data[1] = u.data[1] + v.data[1]; temp.data[2] = u.data[2] + v.data[2]; return temp; } write inline vector operator+(vector& u, vector& v) { return vector( u.data[0] + v.data[0], u.data[1] + v.data[1], u.data[2] + v.data[2] ); } There is no absolute guarantee that the compiler will not build a temporary and do the copy, but at least some, under at least some circumstances, will build the return value in the place in which it is to finally rest. Class/struct return is usually implemented, and especially in cfront, by passing a pointer to a place wherein the return value is to be built, or by providing extra stack space for the return value. In either case, writing the `value builder' constructor in the return statement gives the compiler permission to optimize away the copy constructor invocation by building the result in place. > > Could someone enlighten me? (yes, I looked at the C code generated > > by CC, and am too dumb to understand it). It's not that bad. Use a good editor to match up the parens and split the lines to exhibit the parentheses nesting, then remove truly redundant parens. Remember that `;' becomes `,' and if/then/else is implemented with ?: . A `0' is used to represent a null-else. Most of the rest of the opacity comes from name mangling and the nested- variable prefixes. Those you will get the hang of in time. -- (This man's opinions are his own.) From mole-end Mark Terribile