如何优化MAC搜索

时间:2018-11-01 22:11:15

标签: c arrays search

我必须加快数组(大小: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));
}

要进一步更新问题,请向下滚动到第二个答案

2 个答案:

答案 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;
}