Forums

Forums (http://www.abandonia.com/vbullet/index.php)
-   Programming (http://www.abandonia.com/vbullet/forumdisplay.php?f=25)
-   -   Oop Vs Pp (http://www.abandonia.com/vbullet/showthread.php?t=11538)

Eagg 24-08-2006 03:37 PM

So since the other thread made me curious about this issue, I wrote a small program in C++ to test the statement: "OOP makes programs slower".

I would have written a more complex one, but being busy in real life, I didn't have enough free time to spend.

If you are a programmer, please try to compile the code with your compiler of choice and let it run at least on the default parameters, better would be if you increase the outerloops for more numerical stability.

I also tried to write the procedural function in C, but since I have absolutely no practical expirience with C, I probably didn't do it very well.
Any C programmers are welcome to critise the code and even better improve it, same goes for the C++ part, of course.
I will not comment on the results of the C program so far, because I really think there are better implementations of that one. The first shock, maybe, will be when you see that I included the windows.h in C, but I simply couldn't find a way to stop time using the time.h in a high enough resolution (windows.h GetTickCount() offers a resolution of 2-3ms).

My prediction was that all the different implementations would give out similar if not same results (duration).
A good modern compiler should and will create almost identical code compiling a procedural and oop implementation of the same idea.
This shows quite well in my results from Visual Studio 2005 (VC++ 8.0) I think.

What suprised me is that the "heavy oop" version even succeeded in outperforming the procedural function somehow, this is a mystery to me.

Also there is a big difference between the compiler versions and I guess even higher difference between different compilers, which we might see if some of you run the program.

Please feel free to critise anything may it be the code, style or idea behind the programs.
If you think this does not prove anything, please tell me also the reason why not.

So here are the results:

System : Athlon64 San Diego @ 2555 MHz , DDR 426 @CL2-2-2-5
Compiler: VC++ 8.0

:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::.
:: [C++] set: function loops = 10000x10000
:: outer loops = 10
:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::.
:: finished: 100% time elapsed: 25s time left: 0s
:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::.

:: procedural stack average: 201ms :: reference stack time
:: procedural heap average: 407ms :: reference heap time

:: oop heavy stack average: 165ms :: 17% faster
:: oop heavy heap average: 361ms :: 11% faster

:: oop medium stack average: 327ms :: 62% slower
:: oop medium heap average: 394ms :: 3% faster

:: oop light stack average: 324ms :: 61% slower
:: oop light heap average: 390ms :: 4% faster
:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::.
-------------------------------------------------------------------
:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::.
:: [C] set: function loops = 10000x10000
:: outer loops = 100
:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::.
:: finished: 100% time elapsed: 41s time left: 0s
:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::.

:: procedural stack average: 206ms
:: procedural heap average: 209ms
:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::.


System : Athlon64 San Diego @ 2400 MHz , DDR 400 @CL2.5-3-3-6
Compiler: VC++ 7.0

:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::.
:: [C++] set: function loops = 10000x10000
:: outer loops = 10
:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::.
:: finished: 100% time elapsed: 66s time left: 0s
:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::.

:: procedural stack average: 382ms :: reference stack time
:: procedural heap average: 519ms :: reference heap time

:: oop heavy stack average: 1145ms :: 199% slower
:: oop heavy heap average: 1145ms :: 110% slower

:: oop medium stack average: 1225ms :: 220% slower
:: oop medium heap average: 1389ms :: 167% slower

:: oop light stack average: 460ms :: 20% slower
:: oop light heap average: 463ms :: 10% faster
:::::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::.

And here is the source code:

Main.cpp
Code:

/*

Object Oriented Programming vs. Procedural Programming Performance Test (C++ part)

Parameters: program <innerloops>* <outerloops>* <option>*
************innerloops = set function loops to innerloops˛
************outerloops = set outerloops
************option**** = h for heap only functions
************************ s for stack only functions
***********************= optional parameters

Asymptotic behavior: O(innerloops˛*outerloops) (if option set -> *1/2)


~Noam

*/

#include <iostream>
#include <sstream>
#include <windows.h>
#include "OOPfunc.h"

using namespace std;

//int rx, ry;

//procedural
long ploop(int loop) {
****long end, start = GetTickCount();

****int x = 2;
****int y = 3;

****for (int i = 0; i < loop; i++) {
********for (int j = 0; j < loop; j++) {
************x *= y;
************y += x;
********}
****}****
****//rx = x;
****//ry = y;

****end = GetTickCount();
****return end-start;
}

//procedural heap
long ploop2(int *loop) {
****long end, start = GetTickCount();

****int *x = new int;
*****x = 2;
****int *y = new int;
*****y = 3;

****for (int i = 0; i < *loop; i++) {
********for (int j = 0; j < *loop; j++) {
*************x *= *y;
*************y += *x;
********}
****}
****//if (*x != rx || *y != ry) { cout << "---------------------error:p2"; }
****delete x, y;

****end = GetTickCount();
****return end-start;
}

//oop medium
long ooploop1(int loop) {
****long end, start = GetTickCount();

****OOPfunc o;
****int x = 2;
****int y = 3;

****for (int i = 0; i < loop; i++) {
********for (int j = 0; j < loop; j++) {
************o.mult(x, y);
************o.add(y, x);
********}
****}
****//if (x != rx || y != ry) { cout << "---------------------error:o1"; }

****end = GetTickCount();
****return end-start;
}

//oop medium heap
long ooploop2(int *loop) {
****long end, start = GetTickCount();

****OOPfunc *op = new OOPfunc();
****int *x = new int;
*****x = 2;
****int *y = new int;
*****y = 3;

****for (int i = 0; i < *loop; i++) {
********for (int j = 0; j < *loop; j++) {
************op->mult(*x, *y);
************op->add(*y, *x);
********}
****}
****//if (*x != rx || *y != ry) { cout << "---------------------error:o2"; }
****delete op, x, y;

****end = GetTickCount();
****return end-start;
}

//oop light
long ooploop3(int loop) {
****long end, start = GetTickCount();

****OOPfunc o;
****int x = 2;
****int y = 3;
****
****o.loop(x, y, loop);
****//if (x != rx || y != ry) { cout << "---------------------error:o3"; }

****end = GetTickCount();
****return end-start;
}

//oop light heap
long ooploop4(int *loop) {
****long end, start = GetTickCount();

****OOPfunc *op = new OOPfunc();
****int *x = new int;
*****x = 2;
****int *y = new int;
*****y = 3;
****
****op->loop(*x, *y, loop);
****//if (*x != rx || *y != ry) { cout << "---------------------error:o4"; }
****delete op, x, y;

****end = GetTickCount();
****return end-start;
}

//oop heavy
long ooploop5(int loop) {
****long end, start = GetTickCount();

****OOPfunc x;
****OOPfunc y;

****x.set(2);
****y.set(3);
****
****for (int i = 0; i < loop; i++) {********
********for (int j = 0; j < loop; j++) {
************x.mult(y.value);
************y.add(x.value);
********}
****}
****//if (x.value != rx || y.value != ry) { cout << "---------------------error:o5"; }****

****end = GetTickCount();
****return end-start;
}

//oop heavy heap
long ooploop6(int *loop) {
****long end, start = GetTickCount();

****OOPfunc *xp = new OOPfunc(2);
****OOPfunc *yp = new OOPfunc(3);****
****
****for (int i = 0; i < *loop; i++) {
********for (int j = 0; j < *loop; j++) {
************xp->mult(&yp->value);
************yp->add(&xp->value);
********}
****}
****//if (xp->value != rx || yp->value != ry) { cout << "---------------------error:o6"; }****
****delete xp;
****delete yp;

****end = GetTickCount();
****return end-start;
}

void coutP(int totalF, int loop, int i, int p, long execStart) {
****int percent = 100*(i*totalF+p)/(loop*totalF);
****long elapsed = GetTickCount()-execStart;
****long left;
****if (percent == 0) { left = 0; }
****else { left = elapsed/percent*100-elapsed; }
****cout << ":: finished: " << percent << "%"
******** << "** time elapsed: " << elapsed/1000 << "s"
******** << "** time left: " << left/1000 << "s\t\r";
********
}

string compare(long ref, long x) {
****string result;
****stringstream ss;
****if (ref > x) {
********ss << (int) (100 - 100/(float) ref * (float) x);
********ss >> result;
********result.append("% faster");
****}
****else if (ref < x) {
********ss << (int) (100/(float) ref * (float) x - 100);
********ss >> result;
********result.append("% slower");
****}
****else { result = "equal"; }

****return result;
}

int main(int argc, char *argv[]) {****
****int loop1 = 0;
****int loop2 = 0;
****long execStart = GetTickCount();
****bool heapOnly = false;
****bool stackOnly = false;

****if (argc > 1) {
********stringstream ss;
********ss << argv[1];********
********ss >> loop1;****************
****}****
****if (argc > 2) {
********stringstream ss;********
********ss << argv[2];
********ss >> loop2;********
****}****
****if (argc > 3) {
********string s;
********stringstream ss;********
********ss << argv[3];
********ss >> s;
********if (s == "h") { heapOnly = true; }
********if (s == "s") { stackOnly = true; }************
****}
****if (loop1 == 0) { loop1 = 10000; }
****if (loop2 == 0) { loop2 = 10; }****
****
****cout << ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::." << endl
******** << ":: [C++]****** set: function loops = " << loop1 << "x" << loop1 << endl
******** << "::******************** outer loops = " << loop2 << endl
******** << ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::." << endl;
****
****int totalF = 8;****
****long *dur = new long[totalF];

****for (int i = 0; i < totalF; i++) { dur[i] = 0; }
****if (heapOnly || stackOnly) { totalF /= 2; }

****for (int i = 0; i < loop2; i++) {
********if (heapOnly) {
************coutP(totalF, loop2, i, 0, execStart);
************dur[1] += ploop2(&loop1);************
************coutP(totalF, loop2, i, 1, execStart);
************dur[3] += ooploop2(&loop1);************
************coutP(totalF, loop2, i, 2, execStart);
************dur[5] += ooploop4(&loop1);************
************coutP(totalF, loop2, i, 3, execStart);
************dur[7] += ooploop6(&loop1);
************coutP(totalF, loop2, i, 4, execStart);************
********}
********else if (stackOnly) {
************coutP(totalF, loop2, i, 0, execStart);
************dur[0] += ploop(loop1);
************coutP(totalF, loop2, i, 1, execStart);
************dur[2] += ooploop1(loop1);
************coutP(totalF, loop2, i, 2, execStart);
************dur[4] += ooploop3(loop1);
************coutP(totalF, loop2, i, 3, execStart);
************dur[6] += ooploop5(loop1);
************coutP(totalF, loop2, i, 4, execStart);
********}
********else {
************coutP(totalF, loop2, i, 0, execStart);
************dur[0] += ploop(loop1);
************coutP(totalF, loop2, i, 1, execStart);
************dur[1] += ploop2(&loop1);
************coutP(totalF, loop2, i, 2, execStart);
************dur[2] += ooploop1(loop1);
************coutP(totalF, loop2, i, 3, execStart);
************dur[3] += ooploop2(&loop1);
************coutP(totalF, loop2, i, 4, execStart);
************dur[4] += ooploop3(loop1);
************coutP(totalF, loop2, i, 5, execStart);
************dur[5] += ooploop4(&loop1);
************coutP(totalF, loop2, i, 6, execStart);
************dur[6] += ooploop5(loop1);
************coutP(totalF, loop2, i, 7, execStart);
************dur[7] += ooploop6(&loop1);
************coutP(totalF, loop2, i, 8, execStart);
********}
****}
****
****long refStack = dur[0]/loop2;
****long refHeap = dur[1]/loop2;
****
****cout << endl << ":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::." << endl << endl
******** << ":: procedural stack**average: " << refStack << "ms"
******** << " :: reference stack time" << endl
******** << ":: procedural heap** average: " << refHeap << "ms"
******** << " :: reference heap time" << endl << endl
****
******** << ":: oop heavy stack** average: " << dur[6]/loop2 << "ms"
******** << " :: " <<**compare(refStack, dur[6]/loop2) << endl
******** << ":: oop heavy heap****average: " << dur[7]/loop2 << "ms"
******** << " :: " <<**compare(refHeap, dur[7]/loop2) << endl << endl

******** << ":: oop medium stack**average: " << dur[2]/loop2 << "ms"
******** << " :: " <<**compare(refStack, dur[2]/loop2) << endl
******** << ":: oop medium heap** average: " << dur[3]/loop2 << "ms"
******** << " :: " <<**compare(refHeap, dur[3]/loop2) << endl << endl

******** << ":: oop light stack** average: " << dur[4]/loop2 << "ms"
******** << " :: " <<**compare(refStack, dur[4]/loop2) << endl
******** << ":: oop light heap****average: " << dur[5]/loop2 << "ms"
******** << " :: " <<**compare(refHeap, dur[5]/loop2) << endl;
****
****return 0;
}

OOPfunc.h
Code:

class OOPfunc {****
****
public:
****int value;
****bool isSet;

****OOPfunc(int setValue);****
****OOPfunc();****
****void set(int someInt);****
****void mult(int a);
****void add(int a);
****void mult(int *a);
****void add(int *a);
****void mult(int &a, int b);
****void add(int &a, int b);
****void loop(int &a, int &b, int loop);
****void mult(int &a, int *b);
****void add(int &a, int *b);
****void loop(int &a, int &b, int *loop);
};

OOPfunc.cpp
Code:

#include "OOPfunc.h"

OOPfunc::OOPfunc(int setValue) {
****value = setValue;
****isSet = false;
}

OOPfunc::OOPfunc() {
****isSet = false;
}

void OOPfunc::set(int someInt) {
****value = someInt;
****isSet = true;
}

void OOPfunc::mult(int a) {
****value *= a;
}

void OOPfunc::add(int a) {
****value += a;
}

void OOPfunc::mult(int *a) {
****value *= *a;
}

void OOPfunc::add(int *a) {
****value += *a;
}

void OOPfunc::mult(int &a, int b) {
****a *= b;
}

void OOPfunc::add(int &a, int b) {
****a += b;
}

void OOPfunc::loop(int &a, int &b, int loop) {
****for (int i = 0; i < loop; i++) {
********for (int j = 0; j < loop; j++) {
************a *= b;
************b += a;
********}
****}
}

void OOPfunc::mult(int &a, int *b) {
****a *= *b;
}

void OOPfunc::add(int &a, int *b) {
****a += *b;
}

void OOPfunc::loop(int &a, int &b, int *loop) {
****for (int i = 0; i < *loop; i++) {
********for (int j = 0; j < *loop; j++) {
************a *= b;
************b += a;
********}
****}
}

And the beta main.c for C implementation
Code:

/*

Object Oriented Programming vs. Procedural Programming Performance Test (C part)

Parameters: program <innerloops>* <outerloops>*
************innerloops = set function loops to innerloops˛
************outerloops = set outerloops************
***********************= optional parameters

Asymptotic behavior: O(innerloops˛*outerloops)


~Noam

*/

#include <stdio.h>
#include <windows.h>

long ploop1(int loop) {
****long start = GetTickCount();
****int i, j;
****int x = 2;
****int y = 3;

****for (i = 0; i < loop; i++) {
********for (j = 0; j < loop; j++) {
************x *= y;
************y += x;
********}
****}

****return GetTickCount()-start;
}

long ploop2(int *loop) {
****long start = GetTickCount();
****int i, j;****

****int *xp = malloc(sizeof (int));
****int *yp = malloc(sizeof (int));
****if (xp == NULL || yp == NULL) { exit(EXIT_FAILURE); }
*****xp = 2;
*****yp = 3;

****for (i = 0; i < *loop; i++) {
********for (j = 0; j < *loop; j++) {
*************xp *= *yp;
*************yp += *xp;
********}
****}
****free(xp);
****free(yp);

****return GetTickCount()-start;
}

void printP(int totalF, int loop, int i, int p, long execStart) {
****int percent = 100*(i*totalF+p)/(loop*totalF);
****long elapsed = GetTickCount()-execStart;
****long left;
****if (percent == 0) { left = 0; }
****else { left = elapsed/percent*100-elapsed; }

****printf(":: finished: %d%%", percent);
****printf("** time elapsed: %ds", elapsed/1000);
****printf("** time left: %ds\t\r", left/1000);
}


int main(int argc, char *argv[]) {
****long start;
****int loop1 = 0;
****int loop2 = 0;****
****int i;
****long dur1 = 0;
****long dur2 = 0;

****if (argc > 1) {
********loop1 = atoi(argv[1]);********
****}****
****if (argc > 2) {********
********loop2 = atoi(argv[2]);
****}****
****if (loop1 == 0) { loop1 = 10000; }
****if (loop2 == 0) { loop2 = 10; }****

****printf(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::.\n");
****printf(":: [C]**** set: function loops = %dx%d\n", loop1, loop1);
****printf("::**************** outer loops = %d\n", loop2);
****printf(":::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::.\n");

****start = GetTickCount();**

****for (i = 0; i < loop2; i++) {
********printP(2, loop2, i, 0, start);
********dur1 += ploop1(loop1);
********printP(2, loop2, i, 1, start);
********dur2 += ploop2(&loop1);
********printP(2, loop2, i, 2, start);
****}

****printf("\n:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::.\n\n");
****printf(":: procedural stack average: %dms\n", dur1/loop2);
****printf(":: procedural heap**average: %dms\n", dur2/loop2);

****return 0;
}

PS: Isn't there a way to make the code part in a small scrollable window?
PPS: This are console programs and you should start them out of console, not by double clicking the .exe. If you don't want to do it, you need to add a pause at the end of the code otherwise you won't see the result (the windows will close automatically). I didn't do it by myself because I consider it bad coding practice for a console app.

GrimFang4 24-08-2006 04:58 PM

Eagg, I left my code in the other thread. It doesn't matter much what you're doing with OOP or PP, it's that you're working more with functions and pointers in OOP. Functions and pointers will take longer. Only when you use the optimization option of your compiler will the two methods look anything alike in machine code.

To comment on your code without reading much: You shouldn't have the printing statements within your timing range.

Eagg 24-08-2006 05:17 PM

Pointers don't necessarily make programs slower, they are there to improve performance and memory footprint when used correctly.

I don't have any output within the time critical sections as you can clearly see, the loop2 loop is only to make the statistics numerically stable and does not count to any functions duration time.

If you mean the output code that is commented out, it was only there to make sure that all the functions actually work correctly and deliver me the same end result (x, y).


The current time is 07:25 PM (GMT)

Powered by vBulletin® Version 3.7.1
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.