【问题标题】:Performance issues when initializing each class member?初始化每个类成员时的性能问题?
【发布时间】:2018-02-19 13:04:13
【问题描述】:

我认为这个 SO 问题是关于初始化的一般观点,它已经回答了很多:

Should constructor initialize all the data members of the class?

但是,当我的班级有 100 个成员并且我使用 {} 命令初始化每个成员时,我并没有发现任何可能的性能问题,这只是因为 Eclipse 警告我有关未初始化的成员:

成员 'foo' 未在此构造函数中初始化

我的问题:每次实例化这个类时,一个有很多成员 [>50] 的类中的每个成员的初始化是否会导致性能问题?

更新:由于第一个 cmets:我问的是一般情况。 Eclipse 在我的项目中警告我 9 次分为 4 个类!

【问题讨论】:

  • 当你的班级有 100 名成员时,你还有其他问题。
  • 如果你有一个有 100 个成员变量的类,那么我认为你应该仔细看看你的设计。
  • 成员的初始化是担心性能的错误地方,除非你有一些数据来支持你的主张(而且我强烈怀疑这一点)
  • 顺便说一句,“x 对性能有影响吗?”问题的万能答案。总是“测量”!

标签: c++ eclipse initialization initializer-list


【解决方案1】:

这是我使用 gcc 运行的结果。

我用不同数量的类成员测试了它 [5 次并取平均值],但类实例化了 100'000'000 个。

这有点棘手,因为我使用了最高优化级别 -O3,因此我不得不避免编译器优化代码。

有 100 名班级成员:

Initialized class members:      4'484 msec
Not initialized class members:     50 msec

有 25 名班级成员:

Initialized class members:      1'146 msec
Not initialized class members:     50 msec // as expected it didn't change

有 500 名班级成员:

Initialized class members:     22'129 msec
Not initialized class members:     50 msec // as expected it didn't change

我的结论是:

存在 - 在正常情况下 - 没有在所有类成员初始化时存在显着的性能问题。 在正常情况下我的意思是当有一个函数 [with other code] 有 100'000'000 次迭代时,成员初始化真的不算数。

正如 cmets 中所说,一个好的设计不应该有这么多类成员 - 我只是一般好奇。


PS:

我检查了汇编程序列表 - 当然 - 实际上在初始化版本中 gcc 用 movq $0, 40(%rsp) 初始化了每个 int 成员 - 40 是堆栈上的位置。


#include <stdlib.h>
#include <stdio.h>
#include <chrono>
#include <ctime>
#include <utility>

template<typename TimeT = std::chrono::microseconds>
class measure
{
public:
    template<typename F, typename ...Args>
    static typename TimeT::rep execution(F func, Args&&... args)
    {
        auto start = std::chrono::system_clock::now();
        func(std::forward<Args>(args)...);
        auto duration = std::chrono::duration_cast< TimeT> 
                                (std::chrono::system_clock::now() - start);

        return duration.count();
    }
};

class foo
{
   // for uninitialized version remove the {}
   size_t mainValue {};
   size_t classMember0 {};
   ...
   size_t classMember499 {};

public:
    foo( size_t value ) : mainValue (value + 4660) {};
    auto getMainValue() -> size_t { return mainValue; };
};

auto runCode( size_t iterationCount ) -> void
{
    size_t someValue {};
    for ( size_t j = 0 ; j < iterationCount ; ++j )
    {
        foo MyFoo (iterationCount);
        someValue += MyFoo.getMainValue();
    }
    printf( "Result=%ld\n", someValue );   // that the whole code isn't optimized away...
}

int main( int argc, char * argv [] )
{
    if ( argc != 2 )
    {
        printf( "Usage: %s <Start-Value>\n", argv [0] );
        return 0;
    }

    size_t variableValue = (size_t) atof( argv [1] );
    auto threadExecutionTime = measure<>::execution( [&] () { runCode( variableValue ); } );

    printf( "Total execution time was %.3f milliseconds. %s",
                threadExecutionTime / 1000. );
}

【讨论】:

  • 只是一个旁注:一般来说,我对“给予应得的信用”相当挑剔,但在这种情况下,我觉得你的回答可以不用参考我的 cmets。有时我的cmets只是公然关闭。特别是我什至不确定我是否 100% 同意你引用的陈述;)
猜你喜欢
  • 2020-08-05
  • 1970-01-01
  • 2020-01-31
  • 2023-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-10
相关资源
最近更新 更多