【问题标题】:Does it make sense to clear standard container instead of construct and destruct it?清除标准容器而不是构造和破坏它是否有意义?
【发布时间】:2021-09-09 01:35:30
【问题描述】:

假设我有一个函数:

void someFunc(void) {

    std::vector<std::string> contentVector;

    // here are some operations on the vector
}

函数被多次调用。分析器显示 std::__u::vector::vectorstd::__u::vector::~vector 的 CPU 使用率百分比很高。

在函数外部创建向量并在函数开头调用.clear() 有意义吗?

其他标准容器也有同样的问题。

【问题讨论】:

  • 除非你保证没有并发调用。如果有并发调用,在函数外部提升变量将是一场灾难。即使没有。一旦并发性被引入这个系统,它可能是一场灾难。所以我的建议是把局部变量留在本地。
  • 添加一些关于contentVector 的大小、用例和内容的上下文可能会有所帮助。例如:contentVector的大小顺序contentVector是否在多个调用中保持相同的内容?..等
  • "对于其他标准容器也有同样的问题。" 这些问题非常不同,答案也非常不同。
  • 听起来这里的最终仲裁者将是“分析器对更改后的性能有何看法?”
  • 如果你用这个数组在函数中做一些真实的事情,就不应该是这种情况。检查您是否不在 Debug 配置中;它可能会导致此类事情的额外费用。如果问题仍然存在,请显示整个功能代码。还有……在这种情况下,你的“高百分比”是多少?

标签: c++ containers std


【解决方案1】:

清除标准容器而不是构造和销毁它有意义吗?

是的,这很有意义。这取决于你在做什么。使用适合用例的任何内容。

在向量的情况下,您将重用存储,这在某些用例中可能会更好,因此请考虑到这一点。

【讨论】:

    【解决方案2】:

    如果您每次都重新创建向量(作为局部变量),那么该向量每次都必须从堆中分配一个新的内部数组(并且如果您一次一个地向向量添加项目如果不首先调用reserve(),向量可能必须进行多次重新分配,如果它的第一个分配的数组结果不足以容纳您要添加的所有项目);然后当您的方法调用返回时,向量的析构函数将从堆中释放内部分配的数组以避免内存泄漏。

    另一方面,如果将向量保留在方法外部,则向量的内部数组只需分配一次(如果不调用reserve(),可能需要重新分配几次),同样在未来的方法调用中调用clear() 后,内部数组将被重新使用。

    因此,第二种方式会减少使用的 CPU 周期(没有从堆中进行持续分配和取消分配,耶!),但代价是使用在整个时间内分配一块额外的 RAM(因为向量的内部数组将一直存在,并且将足够大以至少容纳您迄今为止最坏情况下的项目数量)。以内存使用换取 CPU 功率是否值得权衡取决于您在做什么、您的机器有多少 RAM、它有多少 CPU 能力等等,所以很难说哪种方法更好而不是“尝试两种方式,衡量性能,然后选择您喜欢的方法”。

    【讨论】:

      【解决方案3】:

      在函数外部创建向量并在函数开头调用 .clear() 有意义吗?

      除非您保证没有并发调用。如果有并发调用,在函数外提升变量将是一场灾难。

      即使没有。一旦将并发引入到这个系统中,这可能是一场灾难。

      详细说明灾难:如果这是一个爬虫功能并读取不同的网站。在函数外使用相同的变量会将两个网站的内容合二为一。

      我的建议是将局部变量留在本地。除非contentVector 总是持有一些数据。那么vector 应该放在别的地方

      【讨论】:

        【解决方案4】:

        这在很大程度上取决于具体情况。

        理想情况下,调用者应该尽可能少地了解函数的工作原理(封装)。如果调用者提供了向量,那么如果调用者传递了错误的向量,就会引入错误的可能性。此外,您使更改函数的实现成为痛苦的维护负担。函数越独立,越安全。

        但是性能可能会受到影响,那就是您可能会在性能关键部分妥协 - 例如紧密循环。不过,您可以拥有函数的 safefast 版本,其中 safe 版本创建一个向量并将其传递给 快速版本。

        void some_function_fast_api(std::vector<std::string>& v) {
        
            // here are some operations on the vector
        }
        
        inline void some_function_safe_api() {
        
            std::vector<std::string> v;
            some_function_fast_api(v);
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-09-17
          • 1970-01-01
          • 2014-06-17
          • 2018-12-24
          • 1970-01-01
          • 1970-01-01
          • 2016-05-16
          相关资源
          最近更新 更多