标签: allocation

分配了alloca的内存在函数结束时或范围结束时被释放?

如果我有这样的功能:

void bla(int size) {
    while(b){
        char tmp[size];
        ......
    }
}
Run Code Online (Sandbox Code Playgroud)

tmp在while循环的每次迭代中被释放,对吗?

如果我写这个函数:

void bla(int size) {
    while(b){
        char* tmp = alloca(size);
        ......
    }
}
Run Code Online (Sandbox Code Playgroud)

tmp在范围结束时或功能结束时被释放?

c stack allocation

9
推荐指数
1
解决办法
1890
查看次数

malloc()/ free()的对齐限制

较旧的K&R(第二版)和其他我读过的C语言文本讨论了动态内存分配器的实现方式,malloc()并且free()通常还提及有关数据类型对齐限制的内容.显然,某些计算机硬件体系结构(CPU,寄存器和内存访问)限制了如何存储和处理某些值类型.例如,可能要求long必须从4的倍数地址开始存储4字节()整数.

主要平台(英特尔和AMD,SPARC,Alpha)对内存分配和内存访问有什么限制(如果有的话),还是可以安全地忽略在特定地址边界上对齐内存分配?

c memory malloc allocation

8
推荐指数
2
解决办法
4752
查看次数

std :: allocator construct/destroy与placement new/p-> ~T()

对于我的一个项目,我正在从头开始编写一些STL容器(我有我的理由).由于我如此密切地模仿STL的功能和接口,我正在尽力遵守策略"如果它与标准构造具有相同的名称,它将尽可能符合标准."

所以,当然我的容器将allocator作为模板参数,这非常好,因为它允许一些自定义分配方案.关于我的问题.

所述std::allocator接口从对象分离结构的存储器分配.同样,它将解除分配与破坏分开.这是有道理的,因为从中获取内存与在c ++中正确构造对象或多或少无关.

因此,有两个构造/释放函数对于默认实现看起来像这样(直接从书中解除):

void construct(pointer p, const T& val)    { new(p) T(val); }
void destroy(pointer p)                    { p->~T(); }
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,构造只是调用placement new和destroy只是调用析构函数.

是否有任何理由使用这些而不仅仅使用placement new和析构函数语法?一个"正确的"分配器可以用另一种方式实现这些吗?或者我保证符合标准的所有分配器实现都会以这种方式实现构造/销毁方法吗?

更重要的是,可以说我可以随时使用std::uninitialized_copystd::uninitialized_fill构建容器的元素吗?

谢谢.

c++ standards allocation

8
推荐指数
1
解决办法
3206
查看次数

分配延迟似乎很高,为什么?

我有一个在低延迟环境中运行的(java)应用程序,它通常处理大约600微米(+/- 100)的指令.当然,随着我们进一步进入微秒空间,您看到的成本延迟会发生变化,现在我们已经注意到2/3的时间用于分配2个核心域对象.

基准测试已将代码的违规部分与现有引用中的对象构造完全隔离,即基本上是一组引用(每个类中约15个)和一些新的列表,但请参阅下面关于确切测量的内容的注释这里.

每个人一直需要~100微米,这对我来说是莫名其妙的,我试图找出原因.一个快速的基准测试表明,一个类似大小的对象充满了字符串需要大约2-3微米到新的,显然这种基准充满了困难,但认为它可能是有用的基线.

这里有2个Q.

  • 如何调查这种行为?
  • 缓慢分配的解释是什么?

请注意,所涉及的硬件是Sun X4600上的Solaris 10 x86,带有8*双核opteron @ 3.2GHz

我们看过的东西包括

  • 检查PrintTLAB统计信息,显示一些缓慢的分配,因此不存在争用.
  • PrintCompilation建议这些代码中的一个不是JIT友好的,虽然Solaris似乎在这里有一些不寻常的行为(即对现代的linux,没有与solaris10类似的老式的Linux现在就可以进行替换)
  • LogCompilation ...有点难以解析,至少可以说这是一项持续的工作,到目前为止还没有什么明显的
  • JVM版本...在6u6和6u14中保持一致,尚未尝试过6u18或最新版本7

任何和所有的想法赞赏

关于各种帖子的评论摘要,试图让事情更清楚

  • 我测量的成本是创造,它通过生成器(像一个内置对象的总成本这些),其私人构造函数调用新的ArrayList几次以及对现有对象设置引用.测量的成本包括设置构建器的成本以及构建器到域对象的转换
  • 编译(通过热点)有明显的影响,但它仍然相对较慢(在这种情况下编译从100micros到~60)
  • 在我的天真基准测试中编译(通过热点)需要将分配时间从~2micros降低到~300ns
  • 延迟不会因年轻的收集算法(ParNew或平行清除)而有所不同

java latency allocation jvm-hotspot low-level

8
推荐指数
1
解决办法
528
查看次数

有没有操作系统为malloc()实现缓冲?

for/while/do中的很多c/malloc()会消耗很多时间,所以我很好奇是否有任何操作系统为快速malloc缓冲内存.

我一直在思考是否可以通过为malloc编写一个"贪婪"的包装来加速malloc的速度.例如,当我要求1MB内存时,初始分配器将分配10MB,而在第二,第三,第四等...调用malloc函数将简单地从块中返回内存,首先分配"正常"方式.当然,如果没有足够的可用内存,你需要分配一个新的贪婪的内存块.

不知何故,我认为某人之前必须做过这件事或类似事情.所以我的问题很简单:这是否能够显着加快内存分配过程.(是的,我可以在提出问题之前尝试过,但如果没有必要,我只是懒得写这样的东西)

c memory malloc allocation calloc

8
推荐指数
1
解决办法
531
查看次数

为什么std :: allocator :: construct和std :: allocator :: destroy模板化元素类型?

std::allocatorconstructdestroy成员函数上构造元素的类型参数化:

template<class T>
  class allocator
{
  public:
    typedef T value_type;
    typedef T* pointer;

    template<class U, class... Args>
      void construct(U *p, Args&&... args);

    template<class U>
      void destroy(U *p);

  ...
};
Run Code Online (Sandbox Code Playgroud)

这是什么理由?为什么他们不采取value_type*pointer?似乎allocator<T>应该只知道如何构造或销毁类型的对象T.

c++ allocation allocator c++11

8
推荐指数
1
解决办法
1072
查看次数

预分配或不预先在Python中预分配列表

什么时候应该而且不应该在python中预先分配列表?例如,我有一个带有2个列表的函数,并从中创建列表列表.很像,但不完全是矩阵乘法.我应该预先分配结果,

X = Len(M)
Y = Len(F)
B = [[None for y in range(Y)] for x in range(X)]
for x in range(X):
    for y in range(Y):
        B[x][y] = foo(M[x], F[y])
return B
Run Code Online (Sandbox Code Playgroud)

或者在我去的时候动态创建它?

B = []
for m in M:
    B.append([])
    for f in F:
        B[-1].append(foo(m, f))
return B
Run Code Online (Sandbox Code Playgroud)

预分配似乎是不必要的,也许更慢,但动态地看起来是混淆的.特别是,B[-1].append(...)似乎难以辨认.

python obfuscation allocation list

8
推荐指数
1
解决办法
9449
查看次数

限制std :: string分配的数量

我有构造一个函数std::string从一个const char*与两个数字,作为参数传递,追加到它的结束.

std::string makeName(const char* name, uint16_t num1, uint16_t num2) {

    std::string new_name(name);
    new_name.reserve(new_name.length()+5);

    new_name += ":";
    new_name += boost::lexical_cast<std::string>(num1);
    new_name += ":";
    new_name += boost::lexical_cast<std::string>(num2);

    return new_name;
}
Run Code Online (Sandbox Code Playgroud)

该函数被调用数千次,以便为堆上分配的小对象创建唯一的名称.

Object* object1= new Object(makeName("Object", i, j)); // i and j are simply loop indices
Run Code Online (Sandbox Code Playgroud)

我发现使用valgrind的massif工具调用makeName会分配大量内存,因为它被调用了很多次.

87.96% (1,628,746,377B) (heap allocation functions) malloc/new/new[], --alloc-fns, etc.

->29.61% (548,226,178B) 0xAE383B7: std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)

| ->26.39% (488,635,166B) 0xAE38F79: std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19)

| | …
Run Code Online (Sandbox Code Playgroud)

c++ valgrind allocation stdstring

8
推荐指数
1
解决办法
525
查看次数

内存分配由编译器优化

在他的演讲"效率与算法,性能与数据结构"中,Chandler Carruth谈到了在C++中需要更好的分配器模型.当前的分配器模型侵入了类型系统,因此很难在许多项目中工作.另一方面,Bloomberg分配器模型不会入侵类型系统,而是基于虚函数调用,这使得编译器无法"看到"分配并对其进行优化.在他的演讲中,他谈到编译器重复删除内存分配(1:06:47).

我花了一些时间来找到一些内存分配优化的例子,但我发现这个代码示例,在clang下编译,优化掉所有的内存分配,只返回1000000而不分配任何东西.

template<typename T>
T* create() { return new T(); }

int main() {
    auto result = 0;
    for (auto i = 0; i < 1000000; ++i) {
        result += (create<int>() != nullptr);
    }

    return result;
}
Run Code Online (Sandbox Code Playgroud)

以下论文http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3664.html也说分配可以在编译器中融合,似乎表明一些编译器已经做了那种排序东西的.

由于我对高效内存分配的策略非常感兴趣,我真的很想理解为什么Chandler Carruth反对Bloomberg模型中的虚拟调用.上面的例子清楚地表明,clang可以在看到分配时优化.

  1. 我希望有一个"真实代码",这个优化是有用的,并且由任何当前的编译器完成
  2. 您是否有任何代码示例,其中不同的分配由anu当前编译器融合?
  3. 你是否理解Chandler Carruth在1:06:47他的讲话中说编译器可以"重复删除"你的分配时的含义?

c++ memory optimization memory-management allocation

8
推荐指数
1
解决办法
1007
查看次数

堆栈分配功能(性能)

在我的小型性能问题调查期间,我注意到一个有趣的堆栈分配功能,这里是测量时间的模板:

#include <chrono>
#include <iostream>

using namespace std;
using namespace std::chrono;

int x; //for simple optimization suppression
void foo();

int main()
{   
    const size_t n = 10000000; //ten millions
    auto start = high_resolution_clock::now();

    for (size_t i = 0; i < n; i++)
    {
        foo();
    }

    auto finish = high_resolution_clock::now();
    cout << duration_cast<milliseconds>(finish - start).count() << endl;
}
Run Code Online (Sandbox Code Playgroud)

现在全部是关于foo()实现,在每个实现中将总共分配500000 ints:

  1. 分配在一个块中:

    void foo()
    {
        const int size = 500000;
        int a1[size];
    
        x = a1[size - …
    Run Code Online (Sandbox Code Playgroud)

c c++ performance stack allocation

8
推荐指数
1
解决办法
259
查看次数