BobDeTunis
BobDeTunis

Reputation: 175

Difference of performance between two simple functions

Supposing I need to call one of these functions millions of times, what are the differences in performance between these two ?

typedef struct s_tuple{
    double  x;
    double  y;
    double  z;
    double  w;
    double  m;
    double  n;
    double  o;
    double  p;
}   t_tuple;

// (1)
t_tuple tuple_mul1(const double q, t_tuple a)
{
    a.x *= q;
    a.y *= q;
    a.z *= q;
    a.w *= q;
    a.m *= q;
    a.n *= q;
    a.o *= q;
    a.p *= q;
    return a;
}

// (2)
t_tuple tuple_mul2(const double q, const t_tuple a)
{
    t_tuple b;

    b.x = a.x * q;
    b.y = a.y * q;
    b.z = a.z * q;
    b.w = a.w * q;
    b.m = a.m * q;
    b.n = a.n * q;
    b.o = a.o * q;
    b.p = a.p * q;
    return b;
}

My thoughts at first:

resource-management:
(2) needs to allocate memory on the stack for b, so in terms of resources 2 requires 64 more bytes than (1) per exec

runtime:
(1) does not allocate memory on the stack so it gains the 'stack-allocating a t_tuple' time compared to (2).

BUT !
I made some tests and I am completely off. Actually, 2 runs faster than 1: for 200 millions calls, (2) execs in ~1s, whereas (1) execs in ~1.55s

Edit: I compiled with cc with no options

Can someone please explain why ?

Here is my runtime-test program:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct s_tuple{
    double  x;
    double  y;
    double  z;
    double  w;
    double  m;
    double  n;
    double  o;
    double  p;
}   t_tuple;

// (1)
t_tuple tuple_mul1(const double q, t_tuple a)
{
    a.x *= q;
    a.y *= q;
    a.z *= q;
    a.w *= q;
    a.m *= q;
    a.n *= q;
    a.o *= q;
    a.p *= q;
    return a;
}

// (2)
t_tuple tuple_mul2(const double q, const t_tuple a)
{
    t_tuple b;

    b.x = a.x * q;
    b.y = a.y * q;
    b.z = a.z * q;
    b.w = a.w * q;
    b.m = a.m * q;
    b.n = a.n * q;
    b.o = a.o * q;
    b.p = a.p * q;
    return b;
}

int main(int ac, char **av)
{
    int         i;
    long int    n;
    double      q;
    t_tuple     a;
    clock_t     start, end;

    q = 0.7;
    a.x = 1.5;
    a.y = 2;
    a.z = 35897.78;
    a.w = 4.6698;
    a.m = 5.5;
    a.n = 1065;
    a.o = 11.6887;
    a.p = 109090808.789;
    if (ac > 1)
    {
        n = atol(av[1]);
        double execution_time;
        start = clock();
        for (i = 0; i < n; i++)
            tuple_mul1(q, a);
            // tuple_mul2(q, a);
        end = clock();
        execution_time = ((double)(end - start))/CLOCKS_PER_SEC;
        printf("exec_time = %f\nn = %.f * 1e6\n", execution_time, n / 1e6);
    }
}

Upvotes: 0

Views: 86

Answers (1)

Vlad Feinstein
Vlad Feinstein

Reputation: 11321

What compiler did you use and with what options?

gcc with -O3 produced identical assembly for both functions: https://godbolt.org/z/YhTW3zzWq

Upvotes: 1

Related Questions