Skip to content
Permalink
Browse files
My conclusion: not competitive with hashtables.
  • Loading branch information
andreasvc committed Sep 9, 2012
1 parent f8869b0 commit dbe4288
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 5 deletions.
@@ -10,11 +10,11 @@ critbit.pdf: critbit.w

#ctangle critbit.w
critbit.o: critbit.c
gcc -Wall -c critbit.c -std=c99 -ggdb
gcc -Wall -O3 -std=c99 -c critbit.c

critbit-test: critbit.o critbit-test.c
gcc -std=c99 -Wall -c critbit-test.c -ggdb
gcc -Wall -O3 -std=c99 -c critbit-test.c
gcc -o critbit-test critbit.o critbit-test.o

clean:
rm *.o critbit-test
rm -f *.o critbit-test
32 README
@@ -6,6 +6,38 @@ This is an adaptation of the original crit-bit code to fixed length byte-strings
the tree is created. The original PDF is left as reference but obviously no
longer reflects the current state of the code.

Benchmarks
----------
A test with keys of 128 bits, against the Python dictionary (invoked from a
Cython module).

Python dict critbit
N = 755330 N = 755330
insert 0.5s insert 1.07s
update 0.65s update 1.04s
lookup 0.52s lookup 0.74s
clear 0.09s clear 0.14s

N = 1553301 N = 1553301
insert 1.26s insert 3.37s
update 1.49s update 3.39s
lookup 1.19s lookup 2.77s
clear 0.26s clear 0.45s

N = 3106602 N = 3106602
insert 2.19s insert 8.9s
update 3.12s update 8.81s
lookup 2.48s lookup 7.61s
clear 0.48s clear 1.12s
python -c 'import tt; tt.main()' 14.40s user 0.50s system 97% cpu 15.281 total
./critbit-test 39.21s user 0.25s system 99% cpu 39.502 total

Python's dictionary is of course hard to compete with, but it seems that the
critbit tree does not scale well in this case of a large number of dense keys.
Pre-allocating nodes to an array might help, but the fundamental problem is that
as (an area of) the tree gets crowded, lots of critical bits need to be traversed
before a leaf node is reached.

Original README
---------------
This code is taken from Dan Bernstein's qhasm and implements a binary
@@ -1,6 +1,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "critbit.h"

typedef struct {
@@ -147,12 +148,128 @@ static void test_allprefixed() {
critbitn_clear(&tree);
}

int
main() {
typedef struct {
unsigned int a;
unsigned long long b;
} Item;
typedef struct {
Item key;
double value;
} ItemEntry;

static void test_perf(long N) {
critbitn_tree tree = {0, sizeof(Item), sizeof(double)};
Item item;
ItemEntry entry;
clock_t start;
void *p;
entry.key = item;
//printf("\nN = %ld\n", N);

// insert elem[i] as key, with elem[i+1] as value
start = clock();
for (unsigned i = 0; i < N; ++i) {
entry.key.a = i % 1023;
entry.key.b = i ^ (i << 6);
entry.value = 0.234;
if (critbitn_insert(&tree, &entry) != 2) abort();;
}
//printf("insert %lgs\n", ((double) (clock() - start)) / CLOCKS_PER_SEC);

start = clock();
for (unsigned i = 0; i < N; ++i) {
entry.key.a = i % 1023;
entry.key.b = i ^ (i << 6);
p = critbitn_lookup(&tree, &entry.key);
if (p == NULL) abort();
if (*(double *)p != 0.234) abort();
entry.value = (i % 10) + 0.432;
if (critbitn_insert(&tree, &entry) != 1) abort();
}
//printf("update %lgs\n", ((double) (clock() - start)) / CLOCKS_PER_SEC);

start = clock();
for (unsigned i = 0; i < N; ++i) {
item.a = i % 1023;
item.b = i ^ (i << 6);
p = critbitn_lookup(&tree, &item);
if (p == NULL) abort();
if (*(double *)p != (i % 10) + 0.432) abort();
}
//printf("lookup %lgs\n", ((double) (clock() - start)) / CLOCKS_PER_SEC);

start = clock();
critbitn_clear(&tree);
//printf("clear %lgs\n", ((double) (clock() - start)) / CLOCKS_PER_SEC);
}

static void test_perf1(long N) {
critbitn_tree trees[1024]; // {0, sizeof(Item), sizeof(double)};
Item item;
ItemEntry entry;
void *p;
clock_t start;
entry.key = item;
printf("\nN = %ld\n", N);
for (unsigned i = 0; i < 1024; ++i) {
trees[i].root = 0;
trees[i].keylen = sizeof(Item);
trees[i].valuelen = sizeof(double);
}

// insert elem[i] as key, with elem[i+1] as value
start = clock();
for (unsigned i = 0; i < N; ++i) {
entry.key.a = i % 1023;
entry.key.b = i ^ (i << 6);
entry.value = 0.234;
if (critbitn_insert(&trees[entry.key.a], &entry) != 2) abort();;
}
printf("insert %lgs\n", ((double) (clock() - start)) / CLOCKS_PER_SEC);

start = clock();
for (unsigned i = 0; i < N; ++i) {
entry.key.a = i % 1023;
entry.key.b = i ^ (i << 6);
p = critbitn_lookup(&trees[entry.key.a], &entry.key);
if (p == NULL) abort();
if (*(double *)p != 0.234) abort();
entry.value = (i % 10) + 0.432;
if (critbitn_insert(&trees[entry.key.a], &entry) != 1) abort();
}
printf("update %lgs\n", ((double) (clock() - start)) / CLOCKS_PER_SEC);

start = clock();
for (unsigned i = 0; i < N; ++i) {
item.a = i % 1023;
item.b = i ^ (i << 6);
p = critbitn_lookup(&trees[item.a], &item);
if (p == NULL) abort();
if (*(double *)p != (i % 10) + 0.432) abort();
}
printf("lookup %lgs\n", ((double) (clock() - start)) / CLOCKS_PER_SEC);

start = clock();
for (unsigned i = 0; i < 1024; ++i)
critbitn_clear(&trees[i]);
printf("clear %lgs\n", ((double) (clock() - start)) / CLOCKS_PER_SEC);
}

int main() {
long N = 1553301;
//for (int a=0; a<1000; ++a) test_perf(10000);
test_perf(755330 / 4);
test_perf(755330 / 2);
test_perf(755330);
test_perf(1553301);
test_perf(2 * 1553301);
return 0;

test_lookup();
test_update();
test_delete();
test_allprefixed();
//test_perf(N);
printf("Succes.\n");
return 0;
}

0 comments on commit dbe4288

Please sign in to comment.