访问成员变量时的性能注意事项

时间:2015-02-10 19:10:04

标签: c++

我有一个数字运算程序,其中我想要解决的方程式由不同类的成员函数表示。每个课程都有几个成员变量,它们是方程式的输入。成员变量目前是基本的,如double和int,但为了更好地与GUI集成,我想用托管变量替换原语;即我想使用一个单独的类来保存变量的名称和值,并处理读取和写入其值。我担心代码的性能和可读性。例如,我宁愿看到"自然"查找代码x = y + 2而不是x.set_value(y.get_value() + 2)

我提出了四种不同的方法,并尝试了每种方法花费的时间(下面的代码)。我使用调试版本在MSVC 2013中编译了这个。我在发布模式下得到了无意义的结果,因为我认为我的循环得到了优化。结果似乎很重要;使用原语或直接访问成员变量需要花费一半时间使用getter / setter函数或转换运算符重载。

我的问题是:我是否正确地测试了这些不同的方法?是否有更好的方法来做我想做的事情?感谢。

#include <iostream>
#include <chrono>

using namespace std;
using namespace std::chrono;

//Class to manage input parameters
struct Parameter {
    double _value = 0.0;
    double Get_value() const {return _value;}
    void Set_value(double value) {_value = value;}
    operator double(){return _value;}
    void operator=(const double& rhs) {_value = rhs;}
};

int main() {
    const size_t NUM_TESTS = 100;       //Number of tests to run
    const size_t MAX_ITER = 1000000;    //Number of iterations to run in each test
    const double x = 2.71828;           //Variable to read from
    double y = 0;                       //Variable to write to
    Parameter test_parameter;       //managed variable to read/write from/to
    double test_primitive = 0.0;    //primitive variable to read/write from/to
    size_t t_primitive = 0;         //Total time spent on primitive variable (microseconds)
    size_t t_managed_cast = 0;      //Time spent on managed variable using cast and assignment operators
    size_t t_managed_getset = 0;    //Time spent on managed variable using getter/setter functions;
    size_t t_managed_direct = 0;    //Time spent on managed variable using direct access of member var.

    for (size_t n = 0; n < NUM_TESTS; ++n) {
        //Test using a primitive variable.
        auto t0 = high_resolution_clock::now();
        for (size_t i = 0; i < MAX_ITER; ++i) {
            test_primitive = x;
            y = test_primitive;
        }
        auto t1 = high_resolution_clock::now();
        t_primitive += duration_cast<microseconds>(t1-t0).count();

        //Test using a managed variable, using cast operator and assignment operator
        t0 = high_resolution_clock::now();
        for (size_t i = 0; i < MAX_ITER; ++i) {
            test_parameter = x;
            y = test_parameter;
        }
        t1 = high_resolution_clock::now();
        t_managed_cast += duration_cast<microseconds>(t1-t0).count();

        //Test using managed variable, using getter/setter member functions
        t0 = high_resolution_clock::now();
        for (size_t i = 0; i < MAX_ITER; ++i) {
            test_parameter.Set_value(x);
            y = test_parameter.Get_value();
        }
        t1 = high_resolution_clock::now();
        t_managed_getset += duration_cast<microseconds>(t1-t0).count();

        //Test using managed variable, using direct public access
        t0 = high_resolution_clock::now();
        for (size_t i = 0; i < MAX_ITER; ++i) {
            test_parameter._value = x;
            y = test_parameter._value;
        }
        t1 = high_resolution_clock::now();
        t_managed_direct += duration_cast<microseconds>(t1-t0).count();
    }

    cout << "Average time for primitive (microseconds): " << t_primitive / NUM_TESTS << endl;
    cout << "Average time for managed with cast (microseconds): " << t_managed_cast / NUM_TESTS << endl;
    cout << "Average time for managed with get/set (microseconds): " << t_managed_getset / NUM_TESTS << endl;
    cout << "Average time for managed with direct access (microseconds): " << t_managed_direct / NUM_TESTS << endl;

    return 0;
}

2 个答案:

答案 0 :(得分:3)

volatile const double x = 2.71828;
volatile double y = 0;
// ^^ VERY IMPORTANT

在那里,我修正了你的基准。

现在再次启用优化,并且只关心启用优化的时序。

答案 1 :(得分:1)

调试版本不会内联这些访问器方法,因此需要更长时间。发布版本不会出现此问题。

尝试使用版本构建,但是制作变量volatile,我相信这会禁用循环优化。