measuring the execution time of static and dynamic binding

consider the code bellow
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
#include<iostream>
#include<ctime>
#include<boost/progress.hpp>
using namespace std;
class parent
{
    public:
    virtual void dynamic_display(){
        cout<<"It is implemented in Parent class\n";
    }
};
 
class child:public parent
{
    
    static int static_count;
    static int dynamic_count;
    public:
    void static_display(){
        int temp,i;
        for (i=0;i<100000;i++)
        temp=temp+i;
        cout<<"Static Function is called"<< static_count<<"times\n";
        static_count=static_count+1;
    }
    void dynamic_display(){
        int temp,i;
        for (i=0;i<100000;i++)
        temp=temp+i;
        cout<<"Dynamic function is called"<<dynamic_count<<"times\n";
        dynamic_count=dynamic_count+1;
    }
};
int child::static_count=1;
int child::dynamic_count=1;
 
int main(){
    clock_t t1;
    clock_t t2;
    child  chld;
    //first call to static method
    t1=clock();
    cout<< "Calculating....";
    chld.static_display();
    t2=clock()-t1;
    cout<<"The number of processor clicks is" <<t2<<"time is"<<((float)t2/CLOCKS_PER_SEC)<<"\n"; 
    //First call to dynamic method
    t1=clock();
    cout<< "Calculating....";
    chld.dynamic_display();
    t2=clock()-t1;
    cout<<"The number of processor clicks is" <<t2<<"time is"<<((float)t2/CLOCKS_PER_SEC)<<"\n"; 
    //second call to static method
    chld.static_display();
    //second call to dynamic method
    chld.dynamic_display();
    //third call to static method
    chld.static_display();
    //third call to dynamic method
    chld.dynamic_display();
    return 0;
}


I am getting the following as output


Calculating....Static Function is called1times
The number of processor clicks is0time is0
Calculating....Dynamic function is called1times
The number of processor clicks is0time is0
Static Function is called2times
Dynamic function is called2times
Static Function is called3times
Dynamic function is called3times



i am actually trying to calculate the time to execute a statically binding method and a dynamically binded one.consider only the first four lines in my output.Why am i not getting the actual result.where have i gone wrong please advice.............
Compiler optimisation maybe?
You're statically binding in both cases, even though one function is virtual.
> i am actually trying to calculate the time to execute a statically binding method and a dynamically binded one.

The extra call overhead for a virtual call is that of the vtable lookup; this would typically be a couple of extra machine instructions.

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
struct A
{
    virtual ~A() ;
    virtual void foo() ;
    void bar() ;
};

void call_virtually( A* pa )
{
    pa->foo() ;

    /*
    > g++ -std=c++11 -Wall -pedantic-errors -fomit-frame-pointer -O3 -c -S test.cc
    __Z14call_virtuallyP1A:
        movl	4(%esp), %ecx
        movl	(%ecx), %eax // get to the vtable
        movl	8(%eax), %eax // look up pointer to foo
        jmp	*%eax // jump to the pointed function
    */
}

void call_non_virtually( A* pa )
{
    pa->bar() ;
    /*
    > g++ -std=c++11 -Wall -pedantic-errors -fomit-frame-pointer -O3 -c -S test.cc
    __Z18call_non_virtuallyP1A:
        movl	4(%esp), %ecx
        jmp	__ZN1A3barEv // jump to A::bar
    */
}


The real run-time overhead is when the non-virtual call can be inlined and the compiler would be able to perform optimizations across the call. This would vary from situation to situation. For instance:

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
80
81
82
83
84
85
86
extern int one ;

struct A
{
    virtual ~A() ;
    virtual void foo() { ++one ; }
    void bar() { ++one ; }
};

int call_virtually( A* pa )
{
    one = 78 ;
    int two = one + 56 ;
    pa->foo() ;
    ++one ;
    --two ;
    pa->foo() ;
    --one ;
    two += 10 ;

    if( two > one )
    {
        return two - one ;
    }
    else
    {
        return one - two ;
    }

    /*
    > g++ -std=c++11 -Wall -pedantic-errors -fomit-frame-pointer -O3 -c -S test.cc
    __Z14call_virtuallyP1A:
        pushl	%ebx
        subl	$8, %esp
        movl	16(%esp), %ebx
        movl	$78, _one
        movl	(%ebx), %eax
        movl	%ebx, %ecx
        call	*8(%eax)
        movl	(%ebx), %eax
        movl	%ebx, %ecx
        addl	$1, _one
        call	*8(%eax)
        movl	_one, %edx
        leal	-1(%edx), %ecx
        cmpl	$142, %ecx
        movl	%ecx, _one
        leal	-144(%edx), %eax
        jg	L3
        movl	$144, %eax
        subl	%edx, %eax
        L3:
        addl	$8, %esp
        popl	%ebx
        ret
	*/
}

int call_non_virtually( A* pa )
{
    one = 78 ; // constant folding: one == 78
    int two = one + 56 ; // // constant folding: two == 134
    pa->bar() ; // inlined, constant folding: one == 79
    ++one ; // constant folding: one == 80
    --two ; // constant folding: two == 133
    pa->bar() ; // inlined, constant folding: one == 81
    --one ; // constant folding: one == 80
    two += 10 ; // constant folding: two == 123

    if( two > one ) // constant folding: true, dead code elimination
    {
        // def-use: assign 80 to one
        return two - one ; // constant folding: return 63 ;
    }
    else
    {
        return one - two ; // dead code elimination
    }
    /*
    > g++ -std=c++11 -Wall -pedantic-errors -fomit-frame-pointer -O3 -c -S test.cc
    __Z18call_non_virtuallyP1A:
        movl	$80, _one
        movl	$63, %eax
        ret
    */
}



Note: In both cases, the overhead is similar to that of calling a function in a shared library (.so or .dll), or that of calling a function via a pointer obtained at run-time.
Topic archived. No new replies allowed.