这真的是一个简单的问题:
我正在编写Go程序。我应该使用QVector<int>
或QVector<Player>
enum Player
{
EMPTY = 0,
BLACK = 1,
WHITE = 2
};
我想当然,使用Player而不是整数将会更慢。但我想知道还有多少,因为我相信使用enum
是更好的编码。
我做了一些关于分配和比较玩家的测试(而不是int
)
QVector<int> vec;
vec.resize(10000000);
int size = vec.size();
for(int i =0; i<size; ++i)
{
vec[i] = 0;
}
for(int i =0; i<size; ++i)
{
bool b = (vec[i] == 1);
}
QVector<Player> vec2;
vec2.resize(10000000);
int size = vec2.size();
for(int i =0; i<size; ++i)
{
vec2[i] = EMPTY;
}
for(int i =0; i<size; ++i)
{
bool b = (vec2[i] == BLACK);
}
基本上,它只慢了10%。在继续之前还有什么我应该知道的吗?
谢谢!
编辑:10%的差异不是我的想象力,它似乎是Qt和QVector特有的。当我使用std :: vector时,速度是相同的
答案 0 :(得分:80)
枚举在编译时完全解析(枚举常量为整数文字,枚举变量为整数变量),使用它们没有速度损失。
通常,平均枚举的基础类型不会大于int
(除非你输入非常大的常量);事实上,§7.2¶5明确地说:
枚举的基础类型是一个整数类型,可以表示枚举中定义的所有枚举器值。它是实现定义的,其中整数类型用作枚举 的基础类型,但基础类型不得大于
int
除非枚举数的值不适合int
或unsigned int
。
你应该在适当的时候使用枚举,因为它们通常会使代码更容易阅读和维护(你有没有试过调试一个充满“幻数”的程序?:S
)。
至于你的结果:可能你的测试方法没有考虑你在“普通”机器上运行代码时的正常速度波动 1 ;您是否尝试过多次(100+次)运行测试并计算您的时间的平均值和标准差?结果应该是兼容的:平均值之间的差异不应大于两个标准差的RSS 2 的1或2倍(假设,通常情况下,波动的高斯分布)。
您可以做的另一项检查是比较生成的汇编代码(使用g ++,您可以使用-S
开关获取它。)
答案 1 :(得分:44)
通常,使用枚举应该对性能完全没有区别。你是怎么测试的?
我自己只是进行了测试。差异是纯粹的噪音。
刚才,我将这两个版本编译成汇编程序。以下是各自的主要功能:
LFB1778:
pushl %ebp
LCFI11:
movl %esp, %ebp
LCFI12:
subl $8, %esp
LCFI13:
movl $65535, %edx
movl $1, %eax
call __Z41__static_initialization_and_destruction_0ii
leave
ret
LFB1774:
pushl %ebp
LCFI10:
movl %esp, %ebp
LCFI11:
subl $8, %esp
LCFI12:
movl $65535, %edx
movl $1, %eax
call __Z41__static_initialization_and_destruction_0ii
leave
ret
基于微基准测试的任何关于性能的陈述是有害的。有太多外来因素扭曲了数据。
答案 2 :(得分:17)
枚举应该不慢。它们被实现为整数。
答案 3 :(得分:3)
如果您使用Visual Studio,您可以创建一个简单的项目
a=Player::EMPTY;
如果右键单击“转到反汇编”,代码将为
mov dword ptr [a],0
因此编译器会替换枚举的值,通常它不会产生任何开销。
答案 4 :(得分:3)
好吧,我做了一些测试,整数和枚举形式没有太大区别。我还添加了一个char形式,它的速度一直快6%(这并不奇怪,因为它使用的内存较少)。然后我只使用了一个char数组而不是一个向量,这个速度提高了300%!既然我们没有得到QVector是什么,它可能是一个数组的包装器,而不是我用过的std :: vector。
这是我使用的代码,使用Dev Studio 2005中的标准发行版选项进行编译。请注意,由于问题中的代码可以优化为零,我已经更改了定时循环(您必须检查汇编代码)。
#include <windows.h>
#include <vector>
#include <iostream>
using namespace std;
enum Player
{
EMPTY = 0,
BLACK = 1,
WHITE = 2
};
template <class T, T search>
LONGLONG TimeFunction ()
{
vector <T>
vec;
vec.resize (10000000);
size_t
size = vec.size ();
for (size_t i = 0 ; i < size ; ++i)
{
vec [i] = static_cast <T> (rand () % 3);
}
LARGE_INTEGER
start,
end;
QueryPerformanceCounter (&start);
for (size_t i = 0 ; i < size ; ++i)
{
if (vec [i] == search)
{
break;
}
}
QueryPerformanceCounter (&end);
return end.QuadPart - start.QuadPart;
}
LONGLONG TimeArrayFunction ()
{
size_t
size = 10000000;
char
*vec = new char [size];
for (size_t i = 0 ; i < size ; ++i)
{
vec [i] = static_cast <char> (rand () % 3);
}
LARGE_INTEGER
start,
end;
QueryPerformanceCounter (&start);
for (size_t i = 0 ; i < size ; ++i)
{
if (vec [i] == 10)
{
break;
}
}
QueryPerformanceCounter (&end);
delete [] vec;
return end.QuadPart - start.QuadPart;
}
int main ()
{
cout << " Char form = " << TimeFunction <char, 10> () << endl;
cout << "Integer form = " << TimeFunction <int, 10> () << endl;
cout << " Player form = " << TimeFunction <Player, static_cast <Player> (10)> () << endl;
cout << " Array form = " << TimeArrayFunction () << endl;
}
答案 5 :(得分:2)
编译器应将enum
转换为整数。它们在编译时被内联,所以一旦你的程序被编译,它应该与你自己使用整数完全一样。
如果您的测试产生不同的结果,测试本身可能会发生一些事情。要么就是这样,要么你的编译器表现得很奇怪。
答案 6 :(得分:2)
这是依赖于实现的,并且枚举和整数很可能具有不同的性能以及相同或不同的汇编代码,尽管它可能是次优编译器的标志。一些获得分歧的方法是: