【问题标题】:What cost does bloated object file carry?臃肿的目标文件会带来什么成本?
【发布时间】:2018-11-22 22:00:37
【问题描述】:

在从事嵌入式项目时,我遇到了一个函数,该函数在应用程序的生命周期中被调用数千次,通常是循环调用,每秒数十次。我想知道是否可以降低它的成本,我发现它的大部分参数在编译期间都是已知的。

让我用一个例子来说明它。

原始的 hpp/cpp 文件可以近似如下:

原始.hpp:

无效示例(bool arg1,bool arg2,const char* 数据);

原始.cpp:

#include "ex1.hpp"
#include <iostream>

void example(bool arg1, bool arg2, const char* data)
{
    if (arg1 && arg2)
    {
        std::cout << "Both true " << data << std::endl;
    }
    else if (!arg1 && arg2) 
    {
        std::cout << "False and true " << data << std::endl;
    }
    else if (arg1 && !arg2) 
    {
        std::cout << "True and false " << data << std::endl;
    }
    else 
    {
        std::cout << "Both false " << data << std::endl;
    }
}

假设,每次调用函数时,arg1 和 arg2 在编译期间都是已知的。参数data 不是,并且由于各种原因,它的处理不能放在头文件中。

但是,所有这些if 语句都可以由编译器通过一点模板魔法来处理:

magic.hpp:

template<bool arg1, bool arg2>
void example(const char* data);

magic.cpp:

#include "ex1.hpp"    
#include <iostream>

template<bool arg1, bool arg2>
struct Processor;

template<>
struct Processor<true, true>
{
    static void process(const char* data)
    {
        std::cout << "Both true " << data << std::endl;
    }
};

template<>
struct Processor<false, true>
{
    static void process(const char* data)
    {
        std::cout << "False and true " << data << std::endl;
    }
};

template<>
struct Processor<true, false>
{
    static void process(const char* data)
    {
        std::cout << "True and false " << data << std::endl;
    }
};

template<>
struct Processor<false, false>
{
    static void process(const char* data)
    {
        std::cout << "Both false " << data << std::endl;
    }
};

template<bool arg1, bool arg2>
void example(const char* data)
{
    Processor<arg1, arg2>::process(data);
}

template void example<true, true>(const char*);
template void example<false, true>(const char*);
template void example<true, false>(const char*);
template void example<false, false>(const char*);

如您所见,即使在这个很小的示例中,cpp 文件也比原始文件大得多。但我确实删除了一些汇编指令!

现在,在我的真实案例中,事情有点复杂,因为我有枚举和结构,而不是两个 bool 参数。长话短说,所有组合都给了我大约一千种组合,所以我有这么多行template void example&lt;something&gt;(const char*);

当然我不是手动生成它们,而是使用宏,但 cpp 文件仍然变得庞大,与原始文件和目标文件相比更糟糕。

所有这一切都是为了删除几个 if 和一个 switch 语句。

我的问题是:大小是模板魔术方法的唯一问题吗?我想知道使用这么多版本的相同功能是否有一些隐藏的成本。我真的节省了一些资源,还是正好相反?

【问题讨论】:

    标签: c++ templates optimization embedded


    【解决方案1】:

    增加二进制文件大小的问题几乎从来都不是文件本身的存储问题——问题是更多的代码意味着在任何时候缓存中可用的程序指令百分比较低,从而导致缓存未命中。如果你在一个紧密的循环中调用相同的实例化,那么让它做更少的工作是很好的。但是如果你经常在不同的模板实例之间来回切换,那么去主内存加载指令的成本可能远远高于你从函数内部删除一些指令所节省的成本。

    不过,这种事情可能很难预测。在这种(以及任何)类型的优化中找到最佳位置的方法是测量。它也可能会跨平台发生变化——尤其是在嵌入式世界中。

    【讨论】:

    • 是什么让您认为 OP 正在使用具有数据或指令缓存的系统?他说他正在使用微控制器。可以是从古董 8051 到 Cortex A 或 PowerPC 的任何东西。我不明白这是如何回答这个问题的。
    • 我现在可以确认有一点缓存,尽管它可能很小,所以它可能是个问题。该答案对其他有类似问题的人也很有用。最后,这个概念被放弃了。
    猜你喜欢
    • 1970-01-01
    • 2015-06-29
    • 1970-01-01
    • 2014-12-30
    • 2015-03-17
    • 1970-01-01
    • 2023-03-23
    • 2011-03-18
    • 2019-09-17
    相关资源
    最近更新 更多