https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61621
Bug ID: 61621
Summary: Normal enum switch slower than test case.
Product: gcc
Version: 4.8.2
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: holger.seelig at yahoo dot de
I detected that a normal enum switch is 1.5 up to 3 times slower than a
'double' enum switch. Below I created a test case for you. Unkomment the marked
lines to get better performace results.
### Compiler options
/usr/bin/g++ -O3 -Wall -std=c++11 test-case.cpp
### test-case.cpp
#include <iostream>
#include <vector>
#include <chrono>
enum InstructionType
{
UNDEFINED,
INT32,
UINT32,
NUMBER,
STRING,
NULL_OBJECT,
OBJECT,
BOOLEAN_OBJECT,
NUMBER_OBJECT,
STRING_OBJECT,
ARRAY_OBJECT,
DATE_OBJECT,
REGEX_OBJECT,
FUNCTION_OBJECT,
ADDRESS,
NOP,
RESULT,
JUMP_IF_ZERO,
MULTIPLICATION_EXPRESSION,
DIVISION_EXPRESSION,
REMAINDER_EXPRESSION,
ADDITION_EXPRESSION,
SUBTRACTION_EXPRESSION,
LESS_EXPRESSION,
RETURN_STATEMENT,
};
int
run (const std::vector <InstructionType> & instructions)
{
int value = 0;
for (size_t i = 0, size = instructions .size (); i < size; ++ i)
{
switch (instructions [i])
{
case UNDEFINED:
case INT32:
case UINT32:
case NUMBER:
case STRING:
case NULL_OBJECT:
case OBJECT:
case BOOLEAN_OBJECT:
case NUMBER_OBJECT:
case STRING_OBJECT:
case ARRAY_OBJECT:
case DATE_OBJECT:
case REGEX_OBJECT:
case FUNCTION_OBJECT:
case ADDRESS:
value += 1;
break;
// UNCOMMENT THE FOLLOWING LINES TO GET BETTER PERFORMANCE
// default:
// {
// switch (instructions [i])
// {
case NOP:
break;
case RESULT:
value += 2;
break;
case JUMP_IF_ZERO:
value ++;
break;
case MULTIPLICATION_EXPRESSION:
value += 3;
break;
case DIVISION_EXPRESSION:
value += 4;
break;
case REMAINDER_EXPRESSION:
value += 5;
break;
case ADDITION_EXPRESSION:
value += 6;
break;
case SUBTRACTION_EXPRESSION:
value += 7;
break;
case LESS_EXPRESSION:
value += 8;
break;
case RETURN_STATEMENT:
value += 9;
break;
// UNCOMMENT THE FOLLOWING LINES TO GET BETTER PERFORMANCE
// default:
// break;
// }
// }
}
}
return value;
}
inline
double
now ()
{
using namespace std::chrono;
return duration_cast <duration <double>> (high_resolution_clock::now ()
.time_since_epoch ()) .count ();
}
int
main (int argc, char **argv)
{
std::cout << "Enum switch performance test!" << std::endl;
std::vector <InstructionType> instructions = {
UNDEFINED,
INT32,
UINT32,
NUMBER,
STRING,
NULL_OBJECT,
OBJECT,
BOOLEAN_OBJECT,
NUMBER_OBJECT,
STRING_OBJECT,
ARRAY_OBJECT,
DATE_OBJECT,
REGEX_OBJECT,
FUNCTION_OBJECT,
ADDRESS,
NOP,
RESULT,
JUMP_IF_ZERO,
MULTIPLICATION_EXPRESSION,
DIVISION_EXPRESSION,
REMAINDER_EXPRESSION,
ADDITION_EXPRESSION,
SUBTRACTION_EXPRESSION,
LESS_EXPRESSION,
RETURN_STATEMENT,
};
int value = 0;
auto t0 = now ();
for (int i = 0; i < 100000000; ++ i)
value += run (instructions);
std::cout << "value: " << value << std::endl;
std::cout << "time: " << now () - t0 << " s" << std::endl;
return 0;
}
################
holger@qualle:~$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.2-19ubuntu1'
--with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs
--enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-4.8 --enable-shared --enable-linker-build-id
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
--with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls
--with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug
--enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap
--enable-plugin --with-system-zlib --disable-browser-plugin
--enable-java-awt=gtk --enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home
--with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64
--with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64
--with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar
--enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686
--with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic
--enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu
--target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)