简体   繁体   English

使用函数指针比 switch 语句慢

[英]Using function pointers is slower than switch statement

I have this piece of code for testing the behaviour of switch statement versus function pointers:我有这段代码用于测试 switch 语句与函数指针的行为:

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


int mySum(int startingValue)
{
    return startingValue += 1;
}

int mySub(int startingValue)
{
    return startingValue -= 1;
}


int main()
{
    time_t rawtime;
    struct tm * timeinfo;

    time(&rawtime);
    timeinfo = localtime(&rawtime);
    printf("USING SWITCH\n");
    printf("Start time: %s", asctime(timeinfo));

    int startingValue = 25;
    int currentOperation = 0;

    // Using switch
    for (long long i = 0; i < 10000000000; i++)
    {
        switch (currentOperation)
        {
            case 1:
                startingValue = mySum(startingValue);
                break;
            case 0:
                startingValue = mySub(startingValue);
                break;
        }

        if (currentOperation)
            currentOperation = 0;
        else
            currentOperation = 1;
    }

    printf("Result is: %d\n", startingValue);

    time(&rawtime);
    timeinfo = localtime(&rawtime);
    printf("End time: %s", asctime(timeinfo));

    printf("\n\n\n");

    time(&rawtime);
    timeinfo = localtime(&rawtime);
    printf("USING FUNCTION POINTERS\n");
    printf("Start time: %s", asctime(timeinfo));

    startingValue = 25;
    currentOperation = 0;

    // Using function pointers
    int (*mySwitchOfFunctionPointers[2])(int x);
    mySwitchOfFunctionPointers[0] = &mySub;
    mySwitchOfFunctionPointers[1] = &mySum;
    for (long long i = 0; i < 10000000000; i++)
    {
        startingValue = (*mySwitchOfFunctionPointers[currentOperation])(startingValue);

        if (currentOperation)
            currentOperation = 0;
        else
            currentOperation = 1;
    }

    printf("Result is: %d\n", startingValue);

    time(&rawtime);
    timeinfo = localtime(&rawtime);
    printf("End time: %s", asctime(timeinfo));

    return 0;
}

The output is this so code executes instantly with switch statement but it needs many seconds with function pointers:输出是这样的,所以代码使用 switch 语句立即执行,但它需要很多秒的函数指针:

USING SWITCH
Start time: Mon Oct 25 18:04:06 2021
Result is: 25
End time: Mon Oct 25 18:04:06 2021



USING FUNCTION POINTERS
Start time: Mon Oct 25 18:04:06 2021
Result is: 25
End time: Mon Oct 25 18:04:34 2021

Compiled with编译为

gcc -c main.c -o test.o -O3 -Wall -Wno-unused -std=c99
gcc test.o -o test

Why the second approach is slower than the first???为什么第二种方法比第一种方法慢??? Is there something wrong in the code?代码有问题吗? Any idea?任何的想法?

The compiler can inline the switch and then the optimizer is smart enough to realize that your entire loop is a no-op so optimizes it out.编译器可以内联开关,然后优化器足够聪明,可以意识到您的整个循环是空操作,因此将其优化。 It does not do this with the function pointers.它不会使用函数指针来做到这一点。 See https://godbolt.org/z/qxxoof5cnhttps://godbolt.org/z/qxxoof5cn

If you change your code to something that the compiler cannot optimize out so trivially you will get very different results.如果您将代码更改为编译器无法优化的内容,那么您将获得非常不同的结果。 For example:例如:

int mySum(int startingValue)
{
    return startingValue += rand();
}

int mySub(int startingValue)
{
    return startingValue -= rand();
}

The compiler optimization argument (-O3) is responsible for this behaviour.编译器优化参数 (-O3) 负责这种行为。

The compiler can optimize the first for -Loop with the switch inside, because it has every needed information about this code.编译器可以用里面的switch优化第一个for -Loop,因为它有关于这段代码的所有需要​​的信息。

Unfortunately the compiler can't optimize code with function-pointers.不幸的是,编译器不能用函数指针优化代码。 Since the compiler do not know what functions are called.由于编译器不知道调用了哪些函数。

If you delete the -O3 argument at compiling, you will see that, function pointers and the switch-case statements need similar times.如果在编译时删除 -O3 参数,您将看到函数指针和switch-case语句需要相似的时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM