增加堆栈大小以使用alloca()?

时间:2013-03-25 23:29:17

标签: c++ c performance memory memory-management

这是两个重叠的问题 - 我希望为大型数组尝试alloca(),而不是在堆上分配动态大小的数组。这样我就可以在不进行堆分配的情况下提高性能。但是,我得到的印象堆栈大小通常都很小?增加堆栈的大小是否有任何缺点,以便我可以充分利用alloca()?是我拥有的RAM越多,我可以按比例增加堆栈大小吗?

EDIT1:最好是Linux

EDIT2:我没有考虑到指定的尺寸 - 我宁愿知道如何判断限制/界限是什么。

4 个答案:

答案 0 :(得分:10)

大多数unix-y平台上的堆栈大小(默认情况下)为8MB,Windows上为1MB(即,因为Windows有a deterministic way for recovering from out of stack problems,而unix-y平台通常会抛出一个通用的SIGSEGV信号)

如果您的分配很大,那么在堆上分配与在堆栈上分配之间不会有太大的性能差异。当然,每个分配的堆栈效率稍高,但如果您的分配很大,分配的数量可能会很小。

如果你想要一个更大的类似堆栈的结构,你总是可以编写自己的分配器,从malloc中获取一个大块,然后以类似堆栈的方式处理分配/释放。

#include <stdexcept>
#include <cstddef>

class StackLikeAllocator
{
    std::size_t usedSize;
    std::size_t maximumSize;
    void *memory;
public:
    StackLikeAllocator(std::size_t backingSize)
    {
        memory = new char[backingSize];
        usedSize = 0;
        maximumSize = backingSize;
    }
    ~StackLikeAllocator()
    {
        delete[] memory;
    }
    void * Allocate(std::size_t desiredSize)
    {
        // You would have to make sure alignment was correct for your
        // platform (Exercise to the reader)
        std::size_t newUsedSize = usedSize + desiredSize;
        if (newUsedSize > maximumSize)
        {
            throw std::bad_alloc("Exceeded maximum size for this allocator.");
        }

        void* result = static_cast<void*>(static_cast<char*>(memory) + usedSize);
        usedSize = newUsedSize;
        return result;
    }

    // If you need to support deallocation then modifying this shouldn't be
    // too difficult
}

答案 1 :(得分:4)

程序主线程获取的默认堆栈大小是特定于编译器(和/或特定于操作系统)的东西,您应该看到相应的文档以了解如何扩大堆栈。

您可能无法将程序的默认堆栈放大到任意大的尺寸。

但是,正如已经指出的那样,您可以在运行时创建一个具有所需大小的堆栈的线程。

无论如何,alloca()对于曾经分配的大缓冲区没有多大好处。您不需要多次释放和重新分配它。

答案 2 :(得分:2)

回答第一个问题:堆栈大小通常比堆大小小(这在大多数Linux应用程序中都适用)。

如果您计划的分配大于 relative 到实际的默认堆栈大小,那么我认为最好从堆中使用动态分配(而不是尝试增加堆栈大小)。使用内存(填充,读取,操作它)的成本可能远远超过分配的成本。在这种情况下,通过从堆栈分配,您不太可能看到可衡量的收益。

答案 3 :(得分:2)

alloca()new / malloc()之间最重要的区别是,当您从当前函数返回时,分配有alloca()的所有内存都将消失。

alloca()仅对小型临时数据结构有用。

它仅对小型数据结构有用,因为大数据结构会破坏堆栈的缓存局部性,这会给您带来相当大的性能影响。数组作为局部变量也是如此。

仅在非常具体的情况下使用alloca()。如果不确定,请不要使用它。

一般规则是:不要在堆栈上放置大数据结构(&gt; = 1k)。堆栈不会扩展。这是一个非常有限的资源。