【问题标题】:Memory footprint optimalization vs performance内存占用优化与性能
【发布时间】:2013-12-05 01:29:20
【问题描述】:

我担心加载大量字符串的 C99 应用程序的内存占用。我有字符串长度的上限,我基本上会做这样的事情(这个语句在循环中):

char* input = (char*)malloc(sizeof (char)* MAX_CHAR_INPUT_SIZE);
scanf_s("%s", input, MAX_CHAR_INPUT_SIZE);

如您所见,如果用户提供的字符串很小,则会浪费大量内存。我唯一的想法是在读取后将该字符串复制到大小合适的内存块,然后释放更大的内存块。这是好方法吗? (我知道这将是 O(N))。

也有人可以向我解释这是如何用高级语言解决的吗? (例如 C# 的 Console.Read())

【问题讨论】:

  • 在其他语言中真的很常见将与变量关联的字符串的类型视为具有不可变状态的实例,这意味着如果用户需要修改状态(编辑字符串或关联与给定变量不同的字符串),创建一个新字符串(创建新字符串背后的逻辑显然取决于用户在做什么)并附加到标签上;这几乎就是它发生的方式。
  • 其他具有可变字符串的语言(例如 StringBuilder,有时用于提高效率)将从较小的大小开始,然后在必要时增加。
  • c++ 中的字符串是可变的,并且应该以两倍的倍数指数增长。

标签: c string memory c99


【解决方案1】:

如果您在循环中执行此操作,则可以在为最终字符串分配内存之前将其读入临时文件:

char input[MAX_CHAR_INPUT_SIZE];

scanf_s("%s", input, sizeof input);

size_t input_size = strlen(input) + 1;
char *input_final = malloc(input_size);
memcpy(input_final, input, input_size);

这样,每个字符串您仍然只能调用一次malloc(),但每次都分配正确的大小。

【讨论】:

    【解决方案2】:

    您应该考虑的一件事是,与 memcpy() 相比,malloc() 是一个非常昂贵的函数,尤其是在涉及并发性时。高性能程序中更常见的策略之一是在线程本地存储中实际预分配尽可能多的缓冲区内存,然后在这些缓冲区之间实际复制数据(包括字符串)以最小化需要共享的状态量。受保护。

    这很有效,因为 CPU 拥有大量廉价的计算资源,并且经过优化可以有效地移动数据。这与数据访问同步场景相反,后者在现代系统中非常复杂(涉及多级缓存层次结构的多核),因此速度很慢。

    同样适用于“托管内存”环境,例如 JVM 和 CLR(使用任何语言)。查看这篇关于高性能 Java 交易系统的文章(方法相同:预分配内存然后广泛复制以最小化共享状态):http://martinfowler.com/articles/lmax.html

    而且,与往常一样,一个人不得热衷于任何编程技术和模式。复制过期很容易导致完美的程序慢得令人难以置信(或不必要地消耗过多的内存)。广泛的基准测试是绝对必要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-24
      • 1970-01-01
      • 2012-06-10
      • 1970-01-01
      • 2016-07-12
      • 2017-02-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多