在我连接mongoose的recv函数后,Berkeley DB工作得很慢

时间:2016-03-06 17:43:03

标签: c mongoose berkeley-db ld-preload

我正在做的事情有点棘手。我试图使用recv挂钩mongoose的LD_PRELOAD函数。在mongoose收到请求后,它首先会将此请求存储到Berkeley DB中,然后继续。
但是,我发现Berkeley DB的存储速度比平常慢得多。存储相同大小的内容,独立程序只需要1000纳秒,但钩住的猫鼬最多可能需要20毫秒。我完全不知道这是怎么发生的。任何帮助将不胜感激。

typedef uint32_t req_id_t;
typedef uint32_t view_id_t;

typedef struct view_stamp_t{
    view_id_t view_id;
    req_id_t req_id;
}view_stamp;

typedef struct db_t{
    DB* bdb_ptr;
}db;

#define BILLION 1000000000L

const char* db_dir="./.db";

uint64_t vstol(view_stamp vs){
    uint64_t result = ((uint64_t)vs.req_id)&0xFFFFFFFFl;
    uint64_t temp = (uint64_t)vs.view_id&0xFFFFFFFFl;
    result += temp<<32;
    return result;
};

void mk_path(char* dest,const char* prefix,const char* db_name){
    memcpy(dest,prefix,strlen(prefix));
    dest[strlen(prefix)] = '/';
    memcpy(dest+strlen(prefix)+1,db_name,strlen(db_name));
    dest[strlen(prefix)+strlen(db_name)+1] = '\0';
    return;
}

db* initialize_db(const char* db_name,uint32_t flag)
{
    db* db_ptr=NULL;
    DB* b_db;
    DB_ENV* dbenv;
    int ret;
    char* full_path = NULL;

    if((ret=mkdir(db_dir,S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH))!=0){
        if(errno!=EEXIST){
            goto db_init_return;
        }
    }

    full_path = (char*)malloc(strlen(db_dir) + strlen(db_name)+2);
    mk_path(full_path,db_dir,db_name);

    if ((ret = db_env_create(&dbenv,0)) != 0) {
        dbenv->err(dbenv, ret, "Environment Created: %s", db_dir);
        goto db_init_return;
    }
    if ((ret = dbenv->open(dbenv,db_dir,DB_CREATE|DB_INIT_CDB|DB_INIT_MPOOL|DB_THREAD, 0)) != 0) {
        goto db_init_return;
    }
    /* Initialize the DB handle */
    if((ret = db_create(&b_db,dbenv,flag))!=0){
        goto db_init_return;
    }

    if((ret = b_db->open(b_db,NULL,db_name,NULL,DB_BTREE,DB_THREAD|DB_CREATE,0))!=0){
        goto db_init_return;
    }
    db_ptr = (db*)(malloc(sizeof(db)));
    db_ptr->bdb_ptr = b_db;

db_init_return:
    if(full_path!=NULL){
        free(full_path);
    }
    return db_ptr;
}

int store_record(db* db_p, size_t key_size, void* key_data, size_t data_size, void* data){
    int ret = 1;
    if((NULL == db_p)||(NULL == db_p->bdb_ptr)){
        if(db_p == NULL){
          printf("DB store_record : db_p is null.\n");
        } else{
          printf("DB store_recor : db_p->bdb_ptr is null.\n");
        }
        goto db_store_return;
    }
    DB* b_db = db_p->bdb_ptr;
    DBT key,db_data;
    memset(&key, 0, sizeof(key));
    memset(&db_data, 0, sizeof(db_data));
    key.data = key_data;
    key.size = key_size;
    db_data.data = data;
    db_data.size = data_size;

    struct timespec start, end;
    uint64_t diff;
    clock_gettime(CLOCK_MONOTONIC, &start);

    if ((ret = b_db->put(b_db,NULL,&key,&db_data,0)) == 0){
    }
    else{
        printf("DB : %s.\n", db_strerror(ret));
    }

    clock_gettime(CLOCK_MONOTONIC, &end);
    diff = BILLION * (end.tv_sec - start.tv_sec) + end.tv_nsec - start.tv_nsec;
    printf("elapsed time = %llu nanoseconds\n", (long long unsigned int) diff);

db_store_return:
    return ret;
}

int i = 1;

view_stamp vs;
db* db_ptr;

ssize_t recv(int sockfd, void *buf, size_t len, int flags)
{
  if (i == 1)
  {
      db_ptr = initialize_db("node_test",0);
      vs.view_id = 0;
      vs.req_id = 0;
  }
  i = 0;
  typedef ssize_t (*orig_recv_type)(int, void *, size_t, int);
  orig_recv_type orig_recv;
  orig_recv = (orig_recv_type) dlsym(RTLD_NEXT, "recv");
  ssize_t ret = orig_recv(sockfd, buf, len, flags);

  vs.req_id++;
  uint64_t record_no = vstol(vs);
  store_record(db_ptr, sizeof(record_no), &record_no, ret, buf);

  return ret;
}

0 个答案:

没有答案