如何优化MAC的搜索
我必须加快在数组(大小:32k)中搜索MAC地址的速度。我想从中获得更好的性能,我编写了一个小示例代码来说明这个问题(请注意,阵列中的MAC将是随机数(随机端口、随机VLAN),并且没有很好的顺序(如示例代码所示)。 现在,我正在寻找如何改进的建议,即加快速度:如何优化MAC的搜索,c,arrays,search,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 s
#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;
}
}
有关问题的进一步更新,请向下滚动至第二个答案风格说明:嵌套的
if()
很难阅读。有些人更喜欢:
int find_mac(int端口、int vlan、l2_mac_t mac){
int i=0;
对于(int i=0;i
[这应该是一个注释,但我需要格式设置。]我遵循了上面的一些建议,并提出了以下代码。我现在已将MAC的数量减少到
1000
,但我已经收到了一些:找不到MAC
消息。
有人能帮我吗?
代码:
#包括
#包括
#包括
#定义最大MAC 1000
#定义短_INIT 0xFFFF
#定义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无符号字符l2_mac_t[6];
类型定义结构l2_s{
int prt;
int vln;
l2_mac_t mac;
}l2_t;
静态无符号短l2hash[MAX_MAC]={0};
int find_mac(int端口、int vlan、l2_mac_t mac);
“填空”选项卡(作废);
void init(void);
void mac_hash_add(int idx,l2_mac_t mac);
静态l2_t arr[MAX_MAC]={0};
//---------------------------------------------------------------------
内部主(空){
int i=0;
int res=0;
init();
填写表格();
对于(i=0;i保持数组排序并使用二进制搜索只要数据结构是一个随机顺序的数组,在找到匹配项之前,你不能做得比线性搜索更好。如果你可以将数据结构更改为其他内容,那么你可以做得更好。哈希映射、跳过列表、二进制搜索树、sqlite数据库等等。可能性是endlesS,这取决于你需要什么和可以使用的(例如,内存、磁盘空间、使用某些许可证的外部库的限制)。但是,即使只是为了保持数组的排序,考虑如何将频繁插入与查找进行比较。对于单个查找,您可能必须遍历整个未排序数组。(事实上,如果没有对手,你就必须这样做)而二进制搜索只需要几个比较,插入是二进制搜索+批量复制+可能ReLoC.OK,一个单一的<代码> MyStase<代码>您的最大时隙的一半,看看需要多少迭代通过数组来抵消成本,然后考虑插入的频率(<代码> MimStase< /代码>)vs查找频率和无结果查找的常见程度(=最坏情况)。此外,您的查询是随机的,还是与以前的查询(例如,如果可能再次查询同一条目,您是否可以缓存或移动该条目)或插入相关的模式(例如,如果最新/最旧的条目更有可能被查询,则相应地更改搜索方向)但是也要考虑实现一个简单的哈希映射。这样的保护条件真的简化了循环。看起来你用哈希来索引ARR,而不经过L2Hash。@ ARKUK<代码> ARR < /C>代表Mac存储的区域,而<代码> L2Hash 是哈希,它应该为每个MAC提供一个快速查找到C。ode>arr
查找相应的条目。我使用find_mac()
中的k
k尝试直接查找(memcmp()进行验证
)如果不正确,我会查看连续的条目,直到找到正确的条目。一旦到达顶部MAX_MAC
,我必须从下至上进行搜索…@Arkku是的,有一些好处,它会首先尝试将条目存储在k
,如果没有成功(因为它已经被占用),它将递增并找到下一个条目-搜索的速度可能比每次通过MAX\u MAC
线性搜索要快得多,这是非常重要的!但您没有利用这一优势,因为您的find\u MAC
已损坏,这正是我最初的评论试图说的。=)在C语言中有十多亿个二叉树实现的例子,所以你必须四处寻找一个你喜欢的,并以此作为应用程序的基础。我链接到的Wikipedia页面介绍了一些基本知识,如果你想尝试的话,还提供了指向更奇特形式的链接。大多数数据库索引都使用某种形式的二叉树进行排序r数据,因为它们简单、快速、高效。
#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));
}
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
}
#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");
}
}
#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;
}