我写了一些假代码,可以解释我在实际应用程序中发现的问题(Arduino 1.6 - https://github.com/maciejmiklas/LEDDisplay):
Display.h: class Display { public: void testRef(); void testVal(); private: typedef struct { uint8_t xOnFirstKit; uint8_t yOnFirstKit; uint8_t xRelKit; uint8_t yRelKit; uint8_t xRelKitSize; uint8_t yRelKitSize; uint8_t xDataBytes; uint8_t xKit; uint8_t yKit; uint8_t xOnKit; uint8_t yOnKit; uint8_t xOnKitSize; uint8_t yOnKitSize; uint8_t xOnScreenIdx; uint8_t yOnScreenIdx; uint8_t yDataIdx; } KitData; inline void paintOnKitRef(KitData *kd); inline void paintOnKitVal(KitData kd); } Display.cpp: #include "Display.h" void Display::testRef(){ KitData *kd = .... for(int i = 0 ; i < 5000 ; i++){ paintOnKitRef(kd); .... } } void Display::testVal(){ KitData *kd = .... for(int i = 0 ; i < 5000 ; i++){ paintOnKitVal(*kd); .... } } inline void Display::paintOnKitRef(KitData *kd){ for(int i = 0 ; i < 100 ; i++){ kd->yDataIdx++; kd->yOnScreenIdx++; ..... } } inline void Display::paintOnKitVal(KitData kd){ for(int i = 0 ; i < 100 ; i++){ kd.yDataIdx++; kd.yOnScreenIdx++; ..... } }
我有结构:KitData
大于16个字节,所以我决定用指针而不是值传递它 - 它按预期工作.
我已经测量了执行时间,看起来像传递值(testVal()
)比传递引用(testRef()
)要快30%.
这是正常的吗?
编辑:
上面的代码只是一个伪代码 - 在我真正的测试方法中:paintOnKitVal()
并且paintOnKitRef()
包含执行许多操作和其他方法的实际代码.这两种方法也做同样的事情 - 唯一的区别是访问方式(通过kd
指针或点表示法).
这是真正的测试类:https://github.com/maciejmiklas/LEDDisplay/blob/callByPoint/Display.cpp
执行测试方法:paint(...)
- 这将使用第211行中的call-by-pointer
注释第211行并从第212行删除注释 - 从现在开始测试将使用按值调用,执行时间将更短.
JSF.. 5
这部分代码绝对没有任何内容,优化器会识别出:
inline void Display::paintOnKitVal(KitData kd){ for(int i = 0 ; i < 100 ; i++){ kd.yDataIdx++; kd.yOnScreenIdx++; } }
你想象你测试了pass by value的性能.但是你真的测试了编译器识别代码什么都不做的事实的能力.
当您通过指针(C程序员可能通过引用调用"但C++程序员不会"通过引用)时,单独的函数不能说什么也不做.优化器需要更广泛地理解整个程序发现缺乏效果.
这部分代码绝对没有任何内容,优化器会识别出:
inline void Display::paintOnKitVal(KitData kd){ for(int i = 0 ; i < 100 ; i++){ kd.yDataIdx++; kd.yOnScreenIdx++; } }
你想象你测试了pass by value的性能.但是你真的测试了编译器识别代码什么都不做的事实的能力.
当您通过指针(C程序员可能通过引用调用"但C++程序员不会"通过引用)时,单独的函数不能说什么也不做.优化器需要更广泛地理解整个程序发现缺乏效果.