繁体   English   中英

在制作大缓冲区时,使用 malloc 分配缓冲区的速度是否比使用静态分配的缓冲区快?

[英]Is using malloc to allocate a buffer faster than using a statically allocated buffer when making large buffers?

我正在尝试制作这样的数组:

char tmp[4][32768];
//code

这是在 function 中,我发现使这个数组全局化会提高程序的速度(不幸的是我不能保持这样,因为 function 在遇到某些数据时会递归调用自身)。 我想让这个 function 更快,但我读过malloc可能会很慢。 那么像这样离开或这样做会更快吗?:

char** tmp;
tmp = malloc(4 * sizeof(char*));
tmp[0] = malloc(32768);
tmp[1] = malloc(32768);
tmp[2] = malloc(32768);
tmp[3] = malloc(32768);
//code
free(tmp[0]);
free(tmp[1]);
free(tmp[2]);
free(tmp[3]);
free(tmp);

这不是更快或更慢的问题。 这是你是否炸毁堆栈的问题。

您正在创建一个大小为 128K 的数组,该数组对于局部变量来说相当大,并且局部变量通常存在于堆栈中。 如果您递归调用此 function,则每次调用的堆栈上还有 128K。 只需几个递归调用就足以导致堆栈溢出,这可能会导致崩溃。

动态分配 memory 几乎是您唯一的选择。 但是,您可以将其减少为单个分配:

char (*tmp)[32768] = malloc(4 * sizeof *tmp);

这种分配是有效的,因为char [4][32768]类型的二维数组衰减到与上述tmp类型匹配的char (*)[32768]类型的指针。 malloc 返回的malloc足以容纳 4 个char[32768]类型的对象。 这个 memory 是连续的,不像为每个子阵列对malloc进行 4 次单独调用。

在所有条件相同的情况下,通过malloc (或callocrealloc )分配 memory 将比使用auto (本地)数组更慢且更费力,这将比使用static数组慢。

不过,所有事情通常都不是平等的。 正如您所发现的, static数组在处理递归时(或者当您只需要保留多个状态时,就像任何尝试使用strtok标记字符串的人一样"a=b&c=d&e=f"太了解了)。 128K auto阵列有点偏大,如果 function 是递归的,这可能是一个问题,因为堆栈空间对于单个进程通常是有限的。

这是动态 memory 的理想用例,它通常不像堆栈上的 memory 那样受限。 权衡是替代方案会更慢,并且需要您做更多的工作。

究竟慢多少取决于你如何分配和使用它——像这样将它分配为一个连续的块只需要一个malloc (和相应的free )调用,并且应该更适合本地化:

char (*tmp)[32768] = malloc( 4 * sizeof *tmp );
if ( tmp )
{
  for ( size_t i = 0; i < 4; i++ )
    strcpy( tmp[i], some_string ); // or however you intend to use tmp;
  ...
  free( tmp );
}

但是,如果您的堆足够碎片化,您可能无法将其分配为单个连续块,并且必须使用多个malloc (和free )调用来零碎地进行分配:

char **tmp = malloc( 4 * sizeof *tmp );
if ( tmp )
{
  for ( size_t i = 0; i < 4; i++ )
  {
    tmp[i] = malloc( sizeof *tmp[i] * 32768 );
    if ( tmp[i] )
    {
      strcpy( tmp[i], some_string );
    }
  }
  ...
  for ( size_t i = 0; i < 4; i++ )
    free( tmp[i] );
  free( tmp );
}

确定哪个更快并且更适合您的目的的唯一方法是编写多个版本并测量它们的性能。

说了这么多...

不管你的代码有多快,如果它做错了事情,或者给出了错误的答案,或者在输入错误的第一个提示时吐得满地都是,或者暴露了敏感数据,或者为恶意软件提供了一个入口点,或无法修改或维护。 首先是正确性和可维护性的代码,不考虑原始执行速度,然后是上面列出的所有其他问题。 除非您有性能要求(“此操作必须在 X 毫秒内完成”),否则不要担心速度。 先把它做好,然后如果你不满意,你可以随时调整性能。

此外,根据您的代码的 rest 所做的事情,分配和管理 memory 的不同方法之间的差异可能是微不足道的 - 如果您的代码花费大量时间等待某人输入数据,那么额外的几个使用malloc而不是auto阵列所花费的时钟真的无关紧要。 另一方面,如果您在一个紧密的循环中调用此代码数千次,那么这些额外的时钟加起来会产生显着差异。

根据分析测量做出决定,而不是猜测。

暂无
暂无

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

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