Switch vs std::unordered_map

I'm working on a high performance server application and I need to respond according to 3 different opcodes in the received client buffer. Something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// networkMsg[] = unsigned int& NetworkMessage::operator[](const unsigned int index) {
// 	assert(index < m_data.size() && "Index out of range");
// 	return m_data[index];
// }
// NetworkMessage::m_data = std::vector<unsigned int>
// opcode_0, opcode_1, opcode_2 = UINT32
switch(networkMsg[opcode_0]){
	case 0x12:
	{
		switch(networkMsg[opcode_1]){
			// Goes on like this up to switch(networkMsg[opcode_2])
		}
		break;
	}
}


After some point this gets really really long and confusing. So instead I thought maybe using std::unordered_map with handles would be better. Something like:

1
2
3
4
5
6
7
8
9
// handler_map = std::unordered_map<std::string, UINT32>
handler_map.insert(std::make_pair("040D15", OP_CODE_LOGIN));

// Array of function pointers having the size of all OP Codes
int (*handlers[MAX_OP_CODE])(LPVOID);

handlers[OP_CODE_LOGIN] = &HandleLogin; // expecting: int HandleLogin(LPVOID)

int result = handlers[handler_map[networkMsg.getOpcodes()]]((LPVOID)&networkMsg);


As far as I know switch statements in C/C++ are really really fast. Second method on the other hand is a lot easier to keep track of. So if I use std::unordered_map instead of switch would I be sacrificing too much performance ?
Last edited on
If your opcodes are dense and range from 0 to MAX_OP_CODE, an array would get the job done. Just use your opcode as an index into the array. (Your switch statement may be compiled into a similar jump table.)
@cire Thanks for the reply. The problem is that my opcodes are 3 bytes long. For example:

 
BYTE client_packet[] = {0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x03};


packet[2], packet[5] and packet[6] are all opcodes.
It's wouldn't be that difficult to map them onto a 4-byte integer type, but it's probably not worth the effort.
Oh I didn't think about that. That might actually be faster than 3 switch statements. Something like:

1
2
3
4
5
6
UINT32 NetworkMessage::getOpcodes(){
	UINT32 opcode_32 = m_data[6] + (m_data[5] << 8) + (m_data[2] << 16);
	return opcode_32;
}

int result = handlers[networkMsg.getOpcodes()]((LPVOID)&networkMsg);


Thanks for the idea. Probably better than the two other approaches.
Topic archived. No new replies allowed.