Add adaptive quicklist fill factor

Fill factor now has two options:
  - negative (1-5) for size-based ziplist filling
  - positive for length-based ziplist filling with implicit size cap.

Negative offsets define ziplist size limits of:
  -1: 4k
  -2: 8k
  -3: 16k
  -4: 32k
  -5: 64k

Positive offsets now automatically limit their max size to 8k.  Any
elements larger than 8k will be in individual nodes.

Positive ziplist fill factors will keep adding elements
to a ziplist until one of:
  - ziplist has FILL number of elements
    - or -
  - ziplist grows above our ziplist max size (currently 8k)

When using positive fill factors, if you insert a large
element (over 8k), that element will automatically allocate
an individual quicklist node with one element and no other elements will be
in the same ziplist inside that quicklist node.

When using negative fill factors, elements up to the size
limit can be added to one quicklist node.  If an element
is added larger than the max ziplist size, that element
will be allocated an individual ziplist in a new quicklist node.

Tests also updated to start testing at fill factor -5.
This commit is contained in:
Matt Stancliff
2014-11-26 13:42:10 -05:00
parent 60a9418ed9
commit c6bf20c2a7
2 changed files with 173 additions and 74 deletions

View File

@ -38,6 +38,7 @@ typedef struct quicklistNode {
struct quicklistNode *next;
unsigned char *zl;
unsigned int count; /* cached count of items in ziplist */
unsigned int sz; /* ziplist size in bytes */
} quicklistNode;
typedef struct quicklist {
@ -71,20 +72,19 @@ typedef struct quicklistEntry {
/* Prototypes */
quicklist *quicklistCreate(void);
void quicklistRelease(quicklist *quicklist);
quicklist *quicklistPushHead(quicklist *quicklist, const size_t fill,
void *value, const size_t sz);
quicklist *quicklistPushTail(quicklist *quicklist, const size_t fill,
void *value, const size_t sz);
void quicklistPush(quicklist *quicklist, const size_t fill, void *value,
quicklist *quicklistPushHead(quicklist *quicklist, const int fill, void *value,
const size_t sz);
quicklist *quicklistPushTail(quicklist *quicklist, const int fill, void *value,
const size_t sz);
void quicklistPush(quicklist *quicklist, const int fill, void *value,
const size_t sz, int where);
void quicklistAppendZiplist(quicklist *quicklist, unsigned char *zl);
quicklist *quicklistAppendValuesFromZiplist(quicklist *quicklist,
const size_t fill,
unsigned char *zl);
quicklist *quicklistCreateFromZiplist(size_t fill, unsigned char *zl);
void quicklistInsertAfter(quicklist *quicklist, const size_t fill,
const int fill, unsigned char *zl);
quicklist *quicklistCreateFromZiplist(int fill, unsigned char *zl);
void quicklistInsertAfter(quicklist *quicklist, const int fill,
quicklistEntry *node, void *value, const size_t sz);
void quicklistInsertBefore(quicklist *quicklist, const size_t fill,
void quicklistInsertBefore(quicklist *quicklist, const int fill,
quicklistEntry *node, void *value, const size_t sz);
void quicklistDelEntry(quicklistIter *iter, quicklistEntry *entry);
int quicklistReplaceAtIndex(quicklist *quicklist, long index, void *data,
@ -100,7 +100,7 @@ int quicklistIndex(const quicklist *quicklist, const long long index,
quicklistEntry *entry);
void quicklistRewind(quicklist *quicklist, quicklistIter *li);
void quicklistRewindTail(quicklist *quicklist, quicklistIter *li);
void quicklistRotate(quicklist *quicklist, const size_t fill);
void quicklistRotate(quicklist *quicklist, const int fill);
int quicklistPopCustom(quicklist *quicklist, int where, unsigned char **data,
unsigned int *sz, long long *sval,
void *(*saver)(unsigned char *data, unsigned int sz));