高性能仿函数(FixedFunction)-替代std中的function

本文介绍了一种名为FixedFunction的仿函数优化方案,该方案通过减少内存分配和类型转换,显著提高了函数调用的性能,接近于直接调用C++函数的速度。文章详细解释了FixedFunction的实现原理,并通过对比std::function,展示了其在性能上的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文转自:http://www.tanjp.com (即时修正和更新)

 

固定大小仿函数(FixedFunction)

仿函数是C++很多新特性的基础,如 lambda表达式。但是STL提供的std::function兼顾了太多情况,性能不高。于是做了优化,实现代码如下:

template <typename SIGNATURE, size_t STORAGE_SIZE = 128>
class FixedFunction;
template <typename R, typename... ARGS, size_t STORAGE_SIZE>
class FixedFunction<R(ARGS...), STORAGE_SIZE>
{
    typedef R (*FuncPtrType)(ARGS...);
    	typedef R(*MethodType)(void* object_ptr, FuncPtrType free_func_ptr, ARGS... args);
    	typedef void(*AllocType)(void* storage_ptr, void* object_ptr);
public:
    FixedFunction() : mf_function_ptr(nullptr), mf_method_ptr(nullptr), mf_alloc_ptr(nullptr) {}
  
    template <typename FUNC>
    FixedFunction(FUNC&& object) : FixedFunction()
    {
        typedef typename std::remove_reference<FUNC>::type unref_type;
        static_assert(sizeof(unref_type) < STORAGE_SIZE, "functional object doesn't fit into internal storage");
        static_assert(std::is_move_constructible<unref_type>::value, "Should be of movable type");
        mf_method_ptr = [](void* object_ptr, FuncPtrType, ARGS... args) -> R
        {
            return static_cast<unref_type*>(object_ptr)->operator()(args...);
        };
        mf_alloc_ptr = [](void* storage_ptr, void* object_ptr)
        {
            if(object_ptr)
            {
                unref_type* x_object = static_cast<unref_type*>(object_ptr);
                new(storage_ptr) unref_type(std::move(*x_object));
            }
            else
            {
                static_cast<unref_type*>(storage_ptr)->~unref_type();
            }
        };
        mf_alloc_ptr(&ms_storage, &object);
    }
    template <typename RET, typename... PARAMS>
    FixedFunction(RET (*func_ptr)(PARAMS...)) : FixedFunction()
    {
        mf_function_ptr = func_ptr;
        mf_method_ptr = [](void*, FuncPtrType f_ptr, ARGS... args) -> R
        {
            return static_cast<RET (*)(PARAMS...)>(f_ptr)(args...);
        };
    }
    FixedFunction(FixedFunction&& o) : FixedFunction()
    {
        move_from_other(o);
    }
    FixedFunction& operator=(FixedFunction&& o)
    {
        move_from_other(o);
        return *this;
    }
    ~FixedFunction()
    {
        if(mf_alloc_ptr) mf_alloc_ptr(&ms_storage, nullptr);
    }
    R operator()(ARGS... args)
    {
        if(!mf_method_ptr) throw std::runtime_error("call of empty functor");
        return mf_method_ptr(&ms_storage, mf_function_ptr, args...);
    }

private:
	// 不可拷贝
    FixedFunction& operator=(const FixedFunction&) = delete;
    FixedFunction(const FixedFunction&) = delete;

    void move_from_other(FixedFunction& o)
    {
        if(this == &o) return;
        if(mf_alloc_ptr)
        {
            mf_alloc_ptr(&ms_storage, nullptr);
            mf_alloc_ptr = nullptr;
        }
        else
        {
            mf_function_ptr = nullptr;
        }
        mf_method_ptr = o.mf_method_ptr;
        o.mf_method_ptr = nullptr;
        if(o.mf_alloc_ptr)
        {
            mf_alloc_ptr = o.mf_alloc_ptr;
            mf_alloc_ptr(&ms_storage, &o.ms_storage);
        }
        else
        {
            mf_function_ptr = o.mf_function_ptr;
        }
    }
private:
	union
	{
		typename std::aligned_storage<STORAGE_SIZE, sizeof(size_t)>::type ms_storage;
		FuncPtrType mf_function_ptr;
	};
	MethodType mf_method_ptr;
	AllocType mf_alloc_ptr;
};

 

性能测试示例

 

void test1_func()
{
    	std::string s;
    	for (uint32 i = 0; i < 10; ++i)
    	{
    		s.append(1, (char)i);
    	}
    	s.reserve();
}

// 函数直接调用 
for (uint32 i = 0; i < 2000000; ++i)
{
    test_func(); 
}

// std::function包装并调用
std::function<void()> f;
for (uint32 i = 0; i < 2000000; ++i)
{
    f = std::move(std::bind(&test_func));
    f();
}

// FixedFunction包装并调用
FixedFunction<void(), 128> ff;
for (uint32 i = 0; i < 2000000; ++i)
{
    test_func(); 
    ff = std::move(std::bind(&test_func));
    ff();
}

 

结果

执行 函数2000000次

C++函数直接调用耗时(毫秒) :12032

std::function包装调用耗时(毫秒) : 20632

FixedFunction包装调用耗时(毫秒):13442

 

优化效果明显,FixedFunction调用的性能接近C++直接函数调用

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值