【问题标题】:Performance regarding the 'getting' of struct data关于“获取”结构数据的性能
【发布时间】:2014-01-29 05:42:49
【问题描述】:

考虑到从给定结构中“获取”数据的两种可能方法时,我有一个关于性能影响的问题。假设 'name' 变量是相对于 'id' 的值而言的。

假设我有一个结构和枚举如下,

enum GenericId { NONE, ONE, TWO };

struct GenericTypeDefinition {
    GenericId id;
    const char name[8];
    ...
};

假设我想获得这个结构的名称。很简单,我可以只引用 GenericTypeDefinition 结构的实例并引用(或指向)名称成员。很简单。

现在这就是我的性能问题变得相关的地方。假设我需要创建数百个这样的实例,所有这些实例都将被锁定为一定数量的名称和一个唯一的 ID。这些实例将被称为整个程序中可能的“GenericTypeDefinition”的集合。请记住,“name”的值是相对于“id”的值的。我的问题是,如果我实现如下函数(并从结构中删除 name 变量),我是否能够节省一些内存,

struct GenericTypeDefinition { // 'name' is now removed.
    GenericId id;
    ...
};

const char* Definition_ToString(GenericEnum e) {
    switch (e) {
        case NONE: return "Nothing";
        case ZERO: return "Zero is not nothing.";
    ...
}

我认为它会是因为我无需在我创建的每个结构中存储字符串(长度为 8 个字节)。

如果您需要任何澄清,请询问,因为我无法找到更多相关信息。

【问题讨论】:

    标签: c++ c performance


    【解决方案1】:

    如果我理解您的要求,您就是将冗余数据放入您的结构中。本质上,您可以从结构中的 id 获取结构的名称。但是,您也可以将名称直接存储在结构中。

    所以,您是对的 - 不存储名称会节省内存,因为您不会将名称与每个项目一起存储。代价是一点时间。每次需要时,您都需要调用一个函数来为您提供 id 中的名称。您必须权衡这些权衡以确定哪个更重要。

    【讨论】:

    • 感谢您的回复,非常感谢。
    【解决方案2】:

    魔鬼在细节中。答案取决于很多事情。例如,分配这种结构的频率、使用频率以及使用char name[8]; 的频率。

    如果您从结构中删除name,可能会发生以下几种情况:

    • 如果您有很多这种类型的对象和一个好的分配器,您将节省空间。
    • 如果您在某些演算过程中大量使用这些对象,并且只是不时使用name,那么由于缓存性能更好,您将节省时间。
    • 如果您将 name 广泛用于某些计算,并且您的函数 Definition_ToString 只是比您示例中的函数稍微复杂一点,那么您的性能将会下降。

    但是,据我估计,这样的优化只能使程序加速一些小因素。在以微秒为单位计算的情况下,它可能会有所帮助。如果您的程序非常缓慢,请寻找渐近更好的算法。

    【讨论】:

      【解决方案3】:

      在大多数情况下,编译器会为您完成这项工作。它通常将所有 const 字符串文字存储在可执行文件的 RO 部分中。根据优化级别,它甚至可以消除结构中 char 数组占用的内存。所以你的可执行文件大小会增加,但不会影响运行时内存。 但是,由于名称与 ID 相关联,从逻辑上讲,实现第二个版本是有意义的,因此将来如果要添加新 id,则不需要做任何多余的工作。

      【讨论】:

        【解决方案4】:

        在您的第一种情况下,使用正确的 ID 和 NAME 初始化结构的任务意味着程序将在开始时复制文字,即字符串(因为我假设您使用代码中的字符串初始化结构)到 RAM 内存中的另一个空间,char[] 将指向该空间。

        相反,第二种情况意味着该值是从程序本身读取的(文字被硬编码在深度汇编代码中某处的表中),并将返回一个指向它的指针(如果指针不是,请纠正我到程序中的某个位置,但返回的 const char* 存储为变量),因此您确实节省了一些内存。

        我的个人评论是(您可能会看到它超出了问题的范围),即使第二种选择可能会为您节省一些记忆,也意味着 ID 和 NAME 是硬编码,因此离开在运行时排除任何扩展的可能性(即,您想添加更多通过控制台接收的 ID...)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-05-20
          • 2014-01-24
          • 1970-01-01
          • 1970-01-01
          • 2012-01-17
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多