Operator Overloading is slow..

Hi,
I'm a hobbyist 3D graphics programmer and I'm about to create a camera class to enable mouselook in my terrain generation project. I thought I'd do some testing in a console application to see how to optimise C++ functions involving vector maths.

I have been timing my code using a QueryPerformanceCounter timer class and finding the time taken in milliseconds. I typically use a for loop to run the code 20000 times then divide by this number to find an average time.

I created a Vector class with operator overloading for + - and overloading / and * by a scalar float. My main concerns were with optimising normalising and cross product functions. I've found something strange though. The operator overloading calls to / take around 0.000070ms to complete. Yet if I do the same thing in code it only takes 0.000005 ms. Thats a big difference! Why are operator overloading calls so slow? Doing it yourself in code rather than relying on the class operator function is the same thing why is there such a big difference. Is it the function overhead? I'm using Visual Studio 2008.
Here is my code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79

class CVector
{
public:
	float i;
	float j;
	float k;

public:

	CVector();
	CVector(float, float, float);
	CVector operator + (CVector);
	CVector operator - (CVector);
	CVector operator * (float);
	CVector operator / (float);
	void printVector(void);
	void normalise(void);
	float dot(CVector);
	CVector cross(CVector);
	CVector oCross(CVector);
};

CVector CVector::operator / (float divider)
{
	CVector temp;
	temp.i = i / divider;
	temp.j = j / divider;
	temp.k = k / divider;

	return temp;
}



int main()
{
	CVector up(0, 0, 1), out(0, 1, 0), right;  

	right = up.cross(out);

	right.printVector();


	// instantiates a timer
	Timer counter;

	// gets the frequency of the high resolution timer
	//printf("frequency %f\n", counter.PCFrequency);




	long i;
	long num = 20000;

	if (!counter.startTimer())
	{
		printf("Counter failed!\n");
		return 0;
	}

	for (i = 0; i < num; i++)
	{
		//up = right / 8.0;

		up.i = right.i / 8.0;
		up.i = right.j / 8.0;
		up.i = right.k / 8.0;
	}

	double time = counter.getTimer();


	printf("Time is (elapsed):%f, (average):%f\n", time, time/(float)num);

	return 0;
}


With the above code I get an average time of 0.000005
With this :

1
2
3
4
5
6
7
8
for (i = 0; i < num; i++)
	{
	        up = right / 8.0;

		//up.i = right.i / 8.0;
		//up.i = right.j / 8.0;
		//up.i = right.k / 8.0;
	}


I get ~0.000069
Last edited on
You are passing the vector by copy, do it by const reference instead.
You may want to look at std::valarray.

Edit: I wonder if the compiler would optimize
1
2
3
//up.i = right.i / 8.0;
//up.i = right.j / 8.0;
up.i = right.k / 8.0;
Last edited on
Try:
1. Defining the function inside the class to enable function inlining. The relative cost of the function call becomes significant for such short functions.
2. Turning on optimizations.
1. Without turning on optimisations I defined the function in the class and also passed variables as const reference. And there was no change to my timings. The times were on average the same as before.

2. I looked into the options of turning on optimisations and this is what made the biggest difference.
But the first things I did were: You can get down to 0.000026ms just by turning off debug information in the project properties(get rid of the /ZI). (note that dividing in the code sequentially without functions is still 0.000005 ms) . The second thing I did was turning off basic runtime checks (get rid of the /RTC1) this got me down to 0.000015ms. The last thing was to turn on optimisations and this makes the code fast enough to not be noticed by the timer. I get 0ms nomatter how many iterations I set I still get 0. Might be a bug in the timing code or something when optimisations are on. But I can still time some code.
With optimisations on my normalisation vector function is timed and takes ~0.000023ms. This was my costliest operation before taking ~0.000098ms.

Note you can get the equivalent of all the property settings I did by simply going from a debug to release build. Obviously all the debug information and operations slow the code down considerably. I didn't really look at debug or release when writing code before. But it makes sense now. And I'm glad to get a little more insight into the processes that go on in building code.

One thing that is noteworthy is that using inline class functioning, and using variables passed as const reference instead of by value does nothing to improve the speed of the code before or after turning on/off optimisations and debug settings. Writing smarter tighter code doesn't seem to payoff for such short operations and functions, which is annoying, I'm a fan of doing things smarter and smaller.


Anyway thanks for the help, I love programming .. there's always something new to learn.


Without turning on optimisations


Doing speed tests without optimizations on is pointless. All the results you were seeing in debug mode are meaningless.
I didn't really know that before I embarked on this. I didn't really know what differences there are between debug and release versions.
Now I know better.

Note that Disch did not say that debug mode was pointless, only that trying to time an operations performance with debug mode turned on was. Debug mode can be invaluable when you pass that 10K LoC mark and some error comes up out of no where.
I dont know too much about IDEs and getting the most use out of them. I just wanted to learn, bought VS 2008 and went through a whole heap of tutorials. So I have very little knowledge about what the debug mode and release mode actually are and what they do.

I just left out a semi colon somewhere in the code and tried a compile with the settings for the release version. And I still get error messages in the Output window which point me to the line after the semi colon emmision. Thats pretty much all I'm used to getting to get through bugs, I've never used other tools.
So what can you do in a debug build do that you can't do in a release build?
- You can't step through code during execution.

- I don't think it allows you to insert break points in your code (This might be different from one IDE to the next though).

- You can't track variables during execution.

These are really the only ones I use, they are also the only ones I've ever needed but I'm not a professional programmer either.
Topic archived. No new replies allowed.