我必须加快数组(大小:32k)中MAC地址的搜索速度。我想从中获得更好的性能,我写了一些示例代码来说明这个问题(注意数组中的MAC将是随机数(随机端口,随机VLAN),并且排列不正确(如示例代码)。 现在,我正在寻找有关如何改善它的建议,即加快速度:
#include <stdio.h>
#include <string.h>
#define MAX_MAC 32768
typedef unsigned char l2_mac_t[6];
typedef struct l2_s {
int prt;
int vln;
l2_mac_t mac;
}l2_t;
int find_mac(int port, int vlan, l2_mac_t mac);
void fill_mac(void);
static l2_t arr[MAX_MAC] = {0};
int main (void) {
int i = 0;
int res = 0;
fill_mac();
for (i=0;i<MAX_MAC;i++) {
res = find_mac(arr[i].prt,arr[i].vln,arr[i].mac);
if (res%1000 == 0 )
printf("Got MAC %d\n",res);
}
}
int find_mac(int port, int vlan, l2_mac_t mac) {
int i = 0;
for (int i = 0;i< MAX_MAC; i++) {
if (arr[i].prt == port) {
if (arr[i].vln == vlan) {
if (memcmp(arr[i].mac,mac,sizeof(l2_mac_t)) == 0 ) {
//found
return i;
}
}
}
}
}
void fill_mac(void) {
int i = 0;
for (i=0;i<MAX_MAC; i++) {
arr[i].prt = 4;
arr[i].vln = 10;
arr[i].mac[5] = i%255;
arr[i].mac[4] = i%65025;
}
}
下面是获得一些评论后的一些经过编辑的代码:
好吧
我将使用哈希并提出以下内容(这给我一个段错误,因为它不想在init()
中分配这么多的内存)。另外,这感觉像是在用大锤,比下面的MacSum()
,有一种更好的哈希方法,欢迎大家提出建议!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_MAC 32768
#define MacSum(x) (x)[0]*(2^24) \
+(x)[1]*(2^20) \
+(x)[2]*(2^16) \
+(x)[3]*(2^12)\
+(x)[4]*(2^8)\
+(x)[5]
typedef unsigned char l2_mac_t[6];
typedef struct l2_s {
int prt;
int vln;
l2_mac_t mac;
}l2_t;
static unsigned short *L2Hash=0;
int find_mac(int port, int vlan, l2_mac_t mac);
void fill_mac(void);
void init(void);
static l2_t arr[MAX_MAC] = {0};
int main (void) {
int i = 0;
int res = 0;
init();
fill_mac();
for (i=0;i<MAX_MAC;i++) {
res = find_mac(arr[i].prt,arr[i].vln,arr[i].mac);
/*if (res%1000 == 0 )
printf("Got MAC %d\n",res);*/
}
}
int find_mac(int port, int vlan, l2_mac_t mac) {
int i = 0;
int key = 0;
key = MacSum(mac);
if (memcmp(arr[key].mac,mac,sizeof(l2_mac_t)) == 0 ) {
return key;
} else {
for (int i = 0;i< MAX_MAC; i++) {
if (arr[i].prt == port) {
if (arr[i].vln == vlan) {
if (memcmp(arr[i].mac,mac,sizeof(l2_mac_t)) == 0 ) {
return i;
}
}
}
}
}
}
void fill_mac(void) {
int i = 0;
int key = 0;
for (i=0;i<MAX_MAC; i++) {
arr[i].prt = 4;
arr[i].vln = 10;
arr[i].mac[5] = i%255;
arr[i].mac[4] = i%65025;
key = MacSum(arr[i].mac);
L2Hash[key] = i;
}
}
void init(void) {
static int init = 0;
if (init)
return;
L2Hash = (unsigned short*) malloc(0xffffffffffff*sizeof(unsigned short));
}
要进一步更新问题,请向下滚动到第二个答案
答案 0 :(得分:1)
样式注释:嵌套的if()
很难阅读。有些人喜欢:
int find_mac(int port, int vlan, l2_mac_t mac) {
int i = 0;
for (int i = 0;i< MAX_MAC; i++) {
if (arr[i].prt != port) continue;
if (arr[i].vln != vlan) continue;
if (memcmp(arr[i].mac,mac,sizeof(l2_mac_t)) continue;
//found
return i;
}
return WHAT; //!!11!!1
}
[这应该是注释,但我需要格式化。]
答案 1 :(得分:0)
我遵循了上述一些建议,并提出了以下代码。现在,我将MAC的数量减少到1000
,但是我已经收到了一些:Could not find MAC
消息。
有人可以在这里协助我吗?
代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_MAC 1000
#define SHORT_INIT 0xFFFF
#define MacSum(x) (x)[0]*(2^24) \
+(x)[1]*(2^20) \
+(x)[2]*(2^16) \
+(x)[3]*(2^12)\
+(x)[4]*(2^8)\
+(x)[5]
typedef unsigned char l2_mac_t[6];
typedef struct l2_s {
int prt;
int vln;
l2_mac_t mac;
}l2_t;
static unsigned short l2hash[MAX_MAC]={0};
int find_mac(int port, int vlan, l2_mac_t mac);
void fill_mac_tab(void);
void init(void);
void mac_hash_add (int idx, l2_mac_t mac);
static l2_t arr[MAX_MAC] = {0};
//---------------------------------------------------------------------
int main (void) {
int i = 0;
int res = 0;
init();
fill_mac_tab();
for (i=0;i<MAX_MAC;i++) {
res = find_mac(arr[i].prt,arr[i].vln,arr[i].mac);
}
}
//---------------------------------------------------------------------
void init(void) {
int i = 0;
for (i=0;i<MAX_MAC;i++)
l2hash[i] = SHORT_INIT;
}
//---------------------------------------------------------------------
int find_mac(int port, int vlan, l2_mac_t mac) {
int i = 0;
int k = 0;
k = (MacSum(mac))%MAX_MAC;
if (memcmp(arr[k].mac,mac,sizeof(l2_mac_t)) == 0 ) {
printf("Found MAC %02X:%02X:%02X:%02X:%02X:%02X at key %d\n",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],k);
return k;
} else {
for (int i = k;i< MAX_MAC; i++ ) {
if (arr[i].prt != port ) continue;
if (arr[i].vln != vlan ) continue;
if (memcmp( arr[i].mac,mac,sizeof(l2_mac_t) )) continue;
printf("Found MAC %02X:%02X:%02X:%02X:%02X:%02X\n",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
return i;
}
}
printf("Could not find MAC %02X:%02X:%02X:%02X:%02X:%02X\n",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
return -1;
}
//---------------------------------------------------------------------
void fill_mac_tab(void) {
int i = 0;
int o = 0;
int key = 0;
for (i=0;i<MAX_MAC; i++) {
// fill table
arr[i].prt = 4;
arr[i].vln = 10;
arr[i].mac[5] = i%255;
if (i>255)
arr[i].mac[4] = i%65025;
mac_hash_add(i,arr[i].mac);
}
}
void mac_hash_add (int idx, l2_mac_t mac) {
int i = 0;
int o = 0;
int k = 0;
k = (MacSum(arr[idx].mac))%MAX_MAC;
printf("k %d\n",k);
if(l2hash[k] == SHORT_INIT ) {
l2hash[k] = i;
} else {
printf("k %d already used, find next\n",k);
// find next empty spot in hash
for (o=k; o<MAX_MAC; o++) {
if (l2hash[o] != SHORT_INIT ) continue;
printf("using %d\n",o);
l2hash[o] = i;
return;
}
printf("unable to find empty key within range \n");
}
}
上述解决方案如下: 它仍然需要花费大量时间,但是比每次对每个MAC进行整个阵列的线性搜索要好得多。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_MAC 32768
#define SHORT_INIT 0xFFFF
#define OK 0
#define ERROR -1
#define MacSum(x) (x)[0]*(2^24) \
+(x)[1]*(2^20) \
+(x)[2]*(2^16) \
+(x)[3]*(2^12)\
+(x)[4]*(2^8)\
+(x)[5]
typedef unsigned char l2_mac_t[6];
typedef struct l2_s {
int prt;
int vln;
l2_mac_t mac;
}l2_t;
static unsigned short l2hash[MAX_MAC]={0};
int find_mac(int port, int vlan, l2_mac_t mac);
int fill_mac_tab(void);
void init(void);
int mac_hash_add (int idx, l2_mac_t mac);
static l2_t arr[MAX_MAC] = {0};
//---------------------------------------------------------------------
int main (void) {
int i = 0;
int rv = OK;
init();
printf("insert\n");
rv = fill_mac_tab();
if (rv) {
printf("ERROR: fill_mac_tab() returned %d\n",rv);
exit (rv);
}
printf("find\n");
for (i=0;i<MAX_MAC;i++) {
rv = find_mac(arr[i].prt,arr[i].vln,arr[i].mac);
if (rv <0) {
printf("ERROR: find_mac() returned %d\n",rv);
exit(rv);
}
}
}
//---------------------------------------------------------------------
void init(void) {
int i = 0;
for (i=0;i<MAX_MAC;i++)
l2hash[i] = SHORT_INIT;
}
//---------------------------------------------------------------------
int find_mac(int port, int vlan, l2_mac_t mac) {
int i = 0;
int k = 0;
k = (MacSum(mac))%MAX_MAC;
if (memcmp(arr[k].mac,mac,sizeof(l2_mac_t)) == 0 ) {
//printf("Found MAC %02X:%02X:%02X:%02X:%02X:%02X at key %d\n",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5],k);
return k;
} else {
for (int i = k;i< MAX_MAC; i++ ) {
if (arr[i].prt != port ) continue;
if (arr[i].vln != vlan ) continue;
if (memcmp( arr[i].mac,mac,sizeof(l2_mac_t) )) continue;
//printf("Found MAC %02X:%02X:%02X:%02X:%02X:%02X\n",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
return i;
}
//printf("continue search from bottom\n");
for (int i = 0;i< k; i++ ) {
if (arr[i].prt != port ) continue;
if (arr[i].vln != vlan ) continue;
if (memcmp( arr[i].mac,mac,sizeof(l2_mac_t) )) continue;
//printf("Found MAC %02X:%02X:%02X:%02X:%02X:%02X\n",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
return i;
}
}
printf("Could not find MAC %02X:%02X:%02X:%02X:%02X:%02X\n",mac[0],mac[1],mac[2],mac[3],mac[4],mac[5]);
return ERROR;
}
//---------------------------------------------------------------------
int fill_mac_tab(void) {
int i = 0;
int o = 0;
int key = 0;
int rv = OK;
for (i=0;i<MAX_MAC; i++) {
// fill table
arr[i].prt = 4;
arr[i].vln = 10;
arr[i].mac[5] = i%255;
if (i>255)
arr[i].mac[4] = i%65025;
rv = mac_hash_add(i,arr[i].mac);
}
return rv;
}
int mac_hash_add (int idx, l2_mac_t mac) {
int i = 0;
int o = 0;
int k = 0;
int rv = OK;
k = (MacSum(arr[idx].mac))%MAX_MAC;
//printf("k %d\n",k);
if(l2hash[k] == SHORT_INIT ) {
l2hash[k] = i;
} else {
//printf("k %d already used, find next\n",k);
// find next empty spot in hash
for (o=k; o<MAX_MAC; o++) {
if (l2hash[o] != SHORT_INIT ) continue;
//printf("using %d\n",o);
l2hash[o] = i;
return OK;
}
//printf("Continue search in bottom half\n");
for (o=0; o<k; o++) {
if (l2hash[o] != SHORT_INIT ) continue;
//printf("using %d\n",o);
l2hash[o] = i;
return OK;
}
//printf("unable to find empty key within range \n");
rv = ERROR;
}
return rv;
}