早年我写代码时候,也喜欢用#if 0来调试,现在不用了。如下代码主要是跟优化level相关:
- #ifndef REDIS_STATIC
- #define REDIS_STATIC static
- #endif
-
- /* Optimization levels for size-based filling.
- * Note that the largest possible limit is 16k, so even if each record takes
- * just one byte, it still won't overflow the 16 bit count field. */
- static const size_t optimization_level[] = {4096, 8192, 16384, 32768, 65536};
-
- /* Maximum size in bytes of any multi-element ziplist.
- * Larger values will live in their own isolated ziplists.
- * This is used only if we're limited by record count. when we're limited by
- * size, the maximum limit is bigger, but still safe.
- * 8k is a recommended / default size limit */
- #define SIZE_SAFETY_LIMIT 8192
-
- /* Minimum ziplist size in bytes for attempting compression. */
- #define MIN_COMPRESS_BYTES 48
-
- /* Minimum size reduction in bytes to store compressed quicklistNode data.
- * This also prevents us from storing compression if the compression
- * resulted in a larger size than the original data. */
- #define MIN_COMPRESS_IMPROVE 8
-
- /* If not verbose testing, remove all debug printing. */
- #ifndef REDIS_TEST_VERBOSE
- #define D(...)
- #else
- #define D(...) \
- do { \
- printf("%s:%s:%d:\t", __FILE__, __func__, __LINE__); \
- printf(__VA_ARGS__); \
- printf("\n"); \
- } while (0)
- #endif
-
- /* Bookmarks forward declarations */
- #define QL_MAX_BM ((1 << QL_BM_BITS)-1)
- quicklistBookmark *_quicklistBookmarkFindByName(quicklist *ql, const char *name);
- quicklistBookmark *_quicklistBookmarkFindByNode(quicklist *ql, quicklistNode *node);
- void _quicklistBookmarkDelete(quicklist *ql, quicklistBookmark *bm);
-
- /* Simple way to give quicklistEntry structs default values with one call. */
- #define initEntry(e) \
- do { \
- (e)->zi = (e)->value = NULL; \
- (e)->longval = -123456789; \
- (e)->quicklist = NULL; \
- (e)->node = NULL; \
- (e)->offset = 123456789; \
- (e)->sz = 0; \
- } while (0)
-
- /* Create a new quicklist.
- * Free with quicklistRelease(). */
- quicklist *quicklistCreate(void) {
- struct quicklist *quicklist;
-
- quicklist = zmalloc(sizeof(*quicklist));
- quicklist->head = quicklist->tail = NULL;
- quicklist->len = 0;
- quicklist->count = 0;
- quicklist->compress = 0;
- quicklist->fill = -2;
- quicklist->bookmark_count = 0;
- return quicklist;
- }
-
- #define COMPRESS_MAX ((1 << QL_COMP_BITS)-1)
- void quicklistSetCompressDepth(quicklist *quicklist, int compress) {
- if (compress > COMPRESS_MAX) {
- compress = COMPRESS_MAX;
- } else if (compress < 0) {
- compress = 0;
- }
- quicklist->compress = compress;
- }
-
- #define FILL_MAX ((1 << (QL_FILL_BITS-1))-1)
- void quicklistSetFill(quicklist *quicklist, int fill) {
- if (fill > FILL_MAX) {
- fill = FILL_MAX;
- } else if (fill < -5) {
- fill = -5;
- }
- quicklist->fill = fill;
- }
-
- void quicklistSetOptions(quicklist *quicklist, int fill, int depth) {
- quicklistSetFill(quicklist, fill);
- quicklistSetCompressDepth(quicklist, depth);
- }
-
- /* Create a new quicklist with some default parameters. */
- quicklist *quicklistNew(int fill, int compress) {
- quicklist *quicklist = quicklistCreate();
- quicklistSetOptions(quicklist, fill, compress);
- return quicklist;
- }
-
- REDIS_STATIC quicklistNode *quicklistCreateNode(void) {
- quicklistNode *node;
- node = zmalloc(sizeof(*node));
- node->zl = NULL;
- node->count = 0;
- node->sz = 0;
- node->next = node->prev = NULL;
- node->encoding = QUICKLIST_NODE_ENCODING_RAW;
- node->container = QUICKLIST_NODE_CONTAINER_ZIPLIST;
- node->recompress = 0;
- return node;
- }
-
- /* Return cached quicklist count */
- unsigned long quicklistCount(const quicklist *ql) { return ql->count; }
-
- /* Free entire quicklist. */
- void quicklistRelease(quicklist *quicklist) {
- unsigned long len;
- quicklistNode *current, *next;
-
- current = quicklist->head;
- len = quicklist->len;
- while (len--) {
- next = current->next;
-
- zfree(current->zl);
- quicklist->count -= current->count;
-
- zfree(current);
-
- quicklist->len--;
- current = next;
- }
- quicklistBookmarksClear(quicklist);
- zfree(quicklist);
- }
-
- /* Compress the ziplist in 'node' and update encoding details.
- * Returns 1 if ziplist compressed successfully.
- * Returns 0 if compression failed or if ziplist too small to compress. */
- REDIS_STATIC int __quicklistCompressNode(quicklistNode *node) {
- #ifdef REDIS_TEST
- node->attempted_compress = 1;
- #endif
-
- /* Don't bother compressing small values */
- if (node->sz < MIN_COMPRESS_BYTES)
- return 0;
-
- quicklistLZF *lzf = zmalloc(sizeof(*lzf) + node->sz);
-
- /* Cancel if compression fails or doesn't compress small enough */
- if (((lzf->sz = lzf_compress(node->zl, node->sz, lzf->compressed,
- node->sz)) == 0) ||
- lzf->sz + MIN_COMPRESS_IMPROVE >= node->sz) {
- /* lzf_compress aborts/rejects compression if value not compressable. */
- zfree(lzf);
- return 0;
- }
- lzf = zrealloc(lzf, sizeof(*lzf) + lzf->sz);
- zfree(node->zl);
- node->zl = (unsigned char *)lzf;
- node->encoding = QUICKLIST_NODE_ENCODING_LZF;
- node->recompress = 0;
- return 1;
- }
-
- /* Compress only uncompressed nodes. */
- #define quicklistCompressNode(_node) \
- do { \
- if ((_node) && (_node)->encoding == QUICKLIST_NODE_ENCODING_RAW) { \
- __quicklistCompressNode((_node)); \
- } \
- } while (0)
-
- /* Uncompress the ziplist in 'node' and update encoding details.
- * Returns 1 on successful decode, 0 on failure to decode. */
- REDIS_STATIC int __quicklistDecompressNode(quicklistNode *node) {
- #ifdef REDIS_TEST
- node->attempted_compress = 0;
- #endif
-
- void *decompressed = zmalloc(node->sz);
- quicklistLZF *lzf = (quicklistLZF *)node->zl;
- if (lzf_decompress(lzf->compressed, lzf->sz, decompressed, node->sz) == 0) {
- /* Someone requested decompress, but we can't decompress. Not good. */
- zfree(decompressed);
- return 0;
- }
- zfree(lzf);
- node->zl = decompressed;
- node->encoding = QUICKLIST_NODE_ENCODING_RAW;
- return 1;
- }
-
- /* Decompress only compressed nodes. */
- #define quicklistDecompressNode(_node) \
- do { \
- if ((_node) && (_node)->encoding == QUICKLIST_NODE_ENCODING_LZF) { \
- __quicklistDecompressNode((_node)); \
- } \
- } while (0)
-
- /* Force node to not be immediately re-compresable */
- #define quicklistDecompressNodeForUse(_node) \
- do { \
- if ((_node) && (_node)->encoding == QUICKLIST_NODE_ENCODING_LZF) { \
- __quicklistDecompressNode((_node)); \
- (_node)->recompress = 1; \
- } \
- } while (0)
-
- /* Extract the raw LZF data from this quicklistNode.
- * Pointer to LZF data is assigned to '*data'.
- * Return value is the length of compressed LZF data. */
- size_t quicklistGetLzf(const quicklistNode *node, void **data) {
- quicklistLZF *lzf = (quicklistLZF *)node->zl;
- *data = lzf->compressed;
- return lzf->sz;
- }
-
- #define quicklistAllowsCompression(_ql) ((_ql)->compress != 0)
-
- /* Force 'quicklist' to meet compression guidelines set by compress depth.
- * The only way to guarantee interior nodes get compressed is to iterate
- * to our "interior" compress depth then compress the next node we find.
- * If compress depth is larger than the entire list, we return immediately. */
- REDIS_STATIC void __quicklistCompress(const quicklist *quicklist,
- quicklistNode *node) {
- /* If length is less than our compress depth (from both sides),
- * we can't compress anything. */
- if (!quicklistAllowsCompression(quicklist) ||
- quicklist->len < (unsigned int)(quicklist->compress * 2))
- return;
-
- #if 0
- /* Optimized cases for small depth counts */
- if (quicklist->compress == 1) {
- quicklistNode *h = quicklist->head, *t = quicklist->tail;
- quicklistDecompressNode(h);
- quicklistDecompressNode(t);
- if (h != node && t != node)
- quicklistCompressNode(node);
- return;
- } else if (quicklist->compress == 2) {
- quicklistNode *h = quicklist->head, *hn = h->next, *hnn = hn->next;
- quicklistNode *t = quicklist->tail, *tp = t->prev, *tpp = tp->prev;
- quicklistDecompressNode(h);
- quicklistDecompressNode(hn);
- quicklistDecompressNode(t);
- quicklistDecompressNode(tp);
- if (h != node && hn != node && t != node && tp != node) {
- quicklistCompressNode(node);
- }
- if (hnn != t) {
- quicklistCompressNode(hnn);
- }
- if (tpp != h) {
- quicklistCompressNode(tpp);
- }
- return;
- }
- #endif
-
- /* Iterate until we reach compress depth for both sides of the list.a
- * Note: because we do length checks at the *top* of this function,
- * we can skip explicit null checks below. Everything exists. */
- quicklistNode *forward = quicklist->head;
- quicklistNode *reverse = quicklist->tail;
- int depth = 0;
- int in_depth = 0;
- while (depth++ < quicklist->compress) {
- quicklistDecompressNode(forward);
- quicklistDecompressNode(reverse);
-
- if (forward == node || reverse == node)
- in_depth = 1;
-
- /* We passed into compress depth of opposite side of the quicklist
- * so there's no need to compress anything and we can exit. */
- if (forward == reverse || forward->next == reverse)
- return;
-
- forward = forward->next;
- reverse = reverse->prev;
- }
-
- if (!in_depth)
- quicklistCompressNode(node);
-
- /* At this point, forward and reverse are one node beyond depth */
- quicklistCompressNode(forward);
- quicklistCompressNode(reverse);
- }
-
- #define quicklistCompress(_ql, _node) \
- do { \
- if ((_node)->recompress) \
- quicklistCompressNode((_node)); \
- else \
- __quicklistCompress((_ql), (_node)); \
- } while (0)
-
- /* If we previously used quicklistDecompressNodeForUse(), just recompress. */
- #define quicklistRecompressOnly(_ql, _node) \
- do { \
- if ((_node)->recompress) \
- quicklistCompressNode((_node)); \
- } while (0)
-
- /* Insert 'new_node' after 'old_node' if 'after' is 1.
- * Insert 'new_node' before 'old_node' if 'after' is 0.
- * Note: 'new_node' is *always* uncompressed, so if we assign it to
- * head or tail, we do not need to uncompress it. */
- REDIS_STATIC void __quicklistInsertNode(quicklist *quicklist,
- quicklistNode *old_node,
- quicklistNode *new_node, int after) {
- if (after) {
- new_node->prev = old_node;
- if (old_node) {
- new_node->next = old_node->next;
- if (old_node->next)
- old_node->next->prev = new_node;
- old_node->next = new_node;
- }
- if (quicklist->tail == old_node)
- quicklist->tail = new_node;
- } else {
- new_node->next = old_node;
- if (old_node) {
- new_node->prev = old_node->prev;
- if (old_node->prev)
- old_node->prev->next = new_node;
- old_node->prev = new_node;
- }
- if (quicklist->head == old_node)
- quicklist->head = new_node;
- }
- /* If this insert creates the only element so far, initialize head/tail. */
- if (quicklist->len == 0) {
- quicklist->head = quicklist->tail = new_node;
- }
-
- /* Update len first, so in __quicklistCompress we know exactly len */
- quicklist->len++;
-
- if (old_node)
- quicklistCompress(quicklist, old_node);
- }