wangt13
wangt13

Reputation: 1275

How to benchmark/compare Hlist and rbtree?

I am working on an Linux project, and I want to evaluate two main data structures: RBtree and Hash list.

So I got 2 C programs to evaluate their performance (the count of instructions and CPU cycles).

// Hlist_test.c
#include "hlist.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>

#define  MAX_ADDR 10
/* 2^31 + 2^29 - 2^25 + 2^22 - 2^19 - 2^16 + 1 */
#define GOLDEN_RATIO_PRIME_32 0x9e370001UL

static inline uint32_t hash_32(uint32_t val, unsigned int bits)
{
    /* On some cpus multiply is faster, on others gcc will do shifts */
    uint32_t hash = val * GOLDEN_RATIO_PRIME_32;

    /* High bits are more random, so use them. */
    return hash >> (32 - bits);
}

struct hdata_node {
    unsigned int data;
    struct hlist_node list;
};

unsigned int a[] = {0x1000, 0x4000, 0x3000, 0x6000, 0x9000, 0x7000, 0x2000, 0x5000, 0x8000};
static struct hdata_node hnodes[MAX_ADDR] = {
    {.data = 0x1000},
    {.data = 0x4000},
    {.data = 0x3000},
    {.data = 0x6000},
    {.data = 0x9000},
    {.data = 0x7000},
    {.data = 0x2000},
    {.data = 0x5000},
    {.data = 0x8000},
    {.data = 0x9100},
};

int main(int argc, char **argv)
{
    struct hlist_head htable[MAX_ADDR];
    struct hdata_node *hnode = NULL;
    struct hlist_node *hlist = NULL, *n = NULL;
    int i = 0, quit = 1, opt = 0, key;
    unsigned int data;

     for(i = 0; i < MAX_ADDR; i++) {
        INIT_HLIST_HEAD(&htable[i]);
        INIT_HLIST_NODE(&hnodes[i].list);
    }

    for (i = 0;i < MAX_ADDR; i++) {
        key = hnodes[i].data >> 28;
        hlist_add_head(&hnodes[i].list, &htable[key]);
    }

    hlist_for_each_entry_safe(hnode, hlist, n, &htable[9], list) {
        if (hnode->data == 0x9000) {
            //printf("FOUND\n");
            break;
        }
    }
    for (i = 0;i < MAX_ADDR; i++) {
        key = hnodes[i].data >> 28;
        hlist_del(&hnodes[i].list);
    }

    return 0;
}

And rbtree_test.c

/**
 * Based on definition of rbtree in Linux Kernel
 *
 * @author skywang
 * @date 2013/11/18
 */

#include <stdio.h>
#include <stdlib.h>
#include "rbtree.h"

#define LENGTH(a) ( (sizeof(a)) / (sizeof(a[0])) )

typedef int Type;

struct my_node {
    struct rb_node rb_node;
    Type key;
    // ... user data;
};

/*
 * Lookup node.
 */
struct my_node *my_search(struct rb_root *root, Type key)
{
    struct rb_node *rbnode = root->rb_node;

    while (rbnode!=NULL)
    {
        struct my_node *mynode = container_of(rbnode, struct my_node, rb_node);

        if (key < mynode->key)
            rbnode = rbnode->rb_left;
        else if (key > mynode->key)
            rbnode = rbnode->rb_right;
        else
            return mynode;
    }

    return NULL;
}

/*
 * 
 */
int my_insert(struct rb_root *root, Type key)
{
    struct my_node *mynode;
    struct rb_node **tmp = &(root->rb_node), *parent = NULL;

    /* Figure out where to put new node */
    while (*tmp)
    {
        struct my_node *my = container_of(*tmp, struct my_node, rb_node);

        parent = *tmp;
        if (key < my->key)
            tmp = &((*tmp)->rb_left);
        else if (key > my->key)
            tmp = &((*tmp)->rb_right);
        else
            return -1;
    }

    if ((mynode=malloc(sizeof(struct my_node))) == NULL)
        return -1;
    mynode->key = key;

    /* Add new node and rebalance tree. */
    rb_link_node(&mynode->rb_node, parent, tmp);
    rb_insert_color(&mynode->rb_node, root);

    return 0;
}

/*
 * Delete node
 */
void my_delete(struct rb_root *root, Type key)
{
    struct my_node *mynode;

    if ((mynode = my_search(root, key)) == NULL)
        return ;

    // delete mynode
    rb_erase(&mynode->rb_node, root);
    free(mynode);
}

/*
 * print rbtree
 */
static void print_rbtree(struct rb_node *tree, Type key, int direction)
{
    if(tree != NULL)
    {
        if(direction==0)
            printf("%2d(B) is root\n", key);
        else
            printf("%2d(%s) is %2d's %6s child\n", key, rb_is_black(tree)?"B":"R", key, direction==1?"right" : "left");

        if (tree->rb_left)
            print_rbtree(tree->rb_left, rb_entry(tree->rb_left, struct my_node, rb_node)->key, -1);
        if (tree->rb_right)
            print_rbtree(tree->rb_right,rb_entry(tree->rb_right, struct my_node, rb_node)->key,  1);
    }
}

void my_print(struct rb_root *root)
{
    if (root!=NULL && root->rb_node!=NULL)
        print_rbtree(root->rb_node, rb_entry(root->rb_node, struct my_node, rb_node)->key,  0);
}

void main()
{
    unsigned int a[] = {0x1000, 0x4000, 0x3000, 0x6000, 0x9000, 0x7000, 0x2000, 0x5000, 0x8000};
    int i, ilen=LENGTH(a);
    struct rb_root mytree = RB_ROOT;

    printf("== Original data: ");
    for(i=0; i<ilen; i++)
        printf("0x%x ", a[i]);
    printf("\n");

    for (i=0; i < ilen; i++)
    {
        my_insert(&mytree, a[i]);
    }

    // Check tree searching

    my_search(&mytree, a[0]);
    for (i=0; i<ilen; i++) {
        my_delete(&mytree, a[i]);
    }
}

Both programs have 10 items to be inserted, deleted and searched in the data structure.

I am not sure if they are OK for benchmarking their performance?
Or is there any other formal benchtests for Hlist and RBTree I can refer to?

Upvotes: 1

Views: 21

Answers (0)

Related Questions