diff --git a/plageq.c b/plageq.c index be0141a..a743a5b 100644 --- a/plageq.c +++ b/plageq.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -17,8 +17,6 @@ struct node { typedef struct node *iptree; typedef void (*bitsfun)(bits, mask_t, mask_t, mask_t); -pos_t maxpos = 0; - void clearb(uint8_t *b) { bzero(b, DEPTHB); } @@ -41,24 +39,37 @@ int getb(uint8_t *b, int n) { } iptree iptree_new(pos_t size) { - iptree t = malloc(size * sizeof(struct node)); - if (t == 0) error(1, errno, "iptree_new: malloc failed"); - pos_t i; - for(i = 0; i < size; ++i) { - t[i].a[0] = i + 1; - t[i].a[1] = 0; - clearb(t[i].b); - } - t[i].a[0] = 0; + // use mmap to get pages lazily and zeroed + iptree t = mmap(0, size * sizeof(struct node), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + if (t == MAP_FAILED) error(1, errno, "iptree_new: mmap failed"); + // use 2 queues of free nodes + t[0].a[0] = 1; // start of continuous range + t[0].a[1] = 0; // pointer to a chain of free nodes + t[size - 1].a[0] = 1; // end of countinous range marker return t; } pos_t iptree_popfree(iptree t) { - pos_t f = t[0].a[0]; - if (f > maxpos) maxpos = f; - if (!f) error(1, 0, "iptree_popfree: no free nodes left"); - t[0].a[0] = t[f].a[0]; - t[f].a[0] = 0; + pos_t f; + if (t[0].a[1]) { + // try from chain first + f = t[0].a[1]; + t[0].a[1] = t[f].a[0]; // shift pointer to the next node + t[f].a[0] = 0; // clear popped element + } else if (t[0].a[0]) { + // then try if something is left in continuous range + f = t[0].a[0]; // start of the range + if (t[f].a[0]) { + // this is the last element + t[0].a[0] = 0; + t[f].a[0] = 0; // celar popped element + } else { + // more elements are there in the range + ++(t[0].a[0]); + } + } else { + if (!f) error(1, 0, "iptree_popfree: no free nodes left"); + } return f; } @@ -211,6 +222,7 @@ int main(void) { iptree_traverse(t, ip4, print4); iptree_traverse(t, ip6, print6); + pos_t maxpos = t[0].a[0] ? t[0].a[0] : SIZE; double mb_used = nodes2mb(maxpos); double mb_all = nodes2mb(SIZE); fprintf(stderr, "max nodes: %.2f%%, %d / %d, %.2fMB / %.2fMB\n", maxpos / (double)SIZE * 100.0, maxpos, SIZE, mb_used, mb_all); diff --git a/plagmax.c b/plagmax.c index 4d6108b..95f0ed5 100644 --- a/plagmax.c +++ b/plagmax.c @@ -1,5 +1,5 @@ #include -#include +#include #include #include #include @@ -11,33 +11,46 @@ struct node { pos_t a[2]; }; typedef struct node *iptree; typedef void (*bitsfun)(bits, mask_t); -pos_t maxpos = 0; - iptree iptree_new(pos_t size) { - iptree t = malloc(size * sizeof(struct node)); - if (t == 0) error(1, errno, "iptree_new: malloc failed"); - pos_t i; - for(i = 0; i < size; ++i) { - t[i].a[0] = i + 1; - t[i].a[1] = 0; - } - t[i].a[0] = 0; + // use mmap to get pages lazily and zeroed + iptree t = mmap(0, size * sizeof(struct node), PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); + if (t == MAP_FAILED) error(1, errno, "iptree_new: mmap failed"); + // use 2 queues of free nodes + t[0].a[0] = 1; // start of continuous range + t[0].a[1] = 0; // pointer to a chain of free nodes + t[size - 1].a[0] = 1; // end of countinous range marker return t; } pos_t iptree_popfree(iptree t) { - pos_t f = t[0].a[0]; - if (f > maxpos) maxpos = f; - if (!f) error(1, 0, "iptree_popfree: no free nodes left"); - t[0].a[0] = t[f].a[0]; - t[f].a[0] = 0; + pos_t f; + if (t[0].a[1]) { + // try from chain first + f = t[0].a[1]; + t[0].a[1] = t[f].a[0]; // shift pointer to the next node + t[f].a[0] = 0; // clear popped element + } else if (t[0].a[0]) { + // then try if something is left in continuous range + f = t[0].a[0]; // start of the range + if (t[f].a[0]) { + // this is the last element + t[0].a[0] = 0; + t[f].a[0] = 0; // celar popped element + } else { + // more elements are there in the range + ++(t[0].a[0]); + } + } else { + error(1, 0, "iptree_popfree: no free nodes left"); + } return f; } void iptree_pushfree(iptree t, pos_t f) { - t[f].a[0] = t[0].a[0]; - t[f].a[1] = 0; - t[0].a[0] = f; + // elements are pushed only to the pointer chain + t[f].a[0] = t[0].a[1]; // pointer to current head + t[f].a[1] = 0; // clear remaining fields + t[0].a[1] = f; // redirect the pointer to new head } int iptree_is_term(iptree t, pos_t h) { @@ -191,6 +204,7 @@ int main(void) { iptree_traverse(t, ip4, print4); iptree_traverse(t, ip6, print6); + pos_t maxpos = t[0].a[0] ? t[0].a[0] : SIZE; double mb_used = nodes2mb(maxpos); double mb_all = nodes2mb(SIZE); fprintf(stderr, "max nodes: %.2f%%, %d / %d, %.2fMB / %.2fMB\n", maxpos / (double)SIZE * 100.0, maxpos, SIZE, mb_used, mb_all);