Commits

antirez  committed 5169ac1

Implemented zmalloc2, zrealloc2, and zcalloc2. This functions are now used in ziplist, zipmap, and intset implementations as a way to avoid fragmentation at a cost of a bigger memory footprint.

  • Participants
  • Parent commits b02e81b
  • Branches 2.2-zmalloc2

Comments (0)

Files changed (5)

File src/intset.c

 
 /* Create an empty intset. */
 intset *intsetNew(void) {
-    intset *is = zmalloc(sizeof(intset));
+    intset *is = zmalloc2(sizeof(intset));
     is->encoding = INTSET_ENC_INT16;
     is->length = 0;
     return is;
 /* Resize the intset */
 static intset *intsetResize(intset *is, uint32_t len) {
     uint32_t size = len*is->encoding;
-    is = zrealloc(is,sizeof(intset)+size);
+    is = zrealloc2(is,sizeof(intset)+size);
     return is;
 }
 

File src/ziplist.c

 /* Create a new empty ziplist. */
 unsigned char *ziplistNew(void) {
     unsigned int bytes = ZIPLIST_HEADER_SIZE+1;
-    unsigned char *zl = zmalloc(bytes);
+    unsigned char *zl = zmalloc2(bytes);
     ZIPLIST_BYTES(zl) = bytes;
     ZIPLIST_TAIL_OFFSET(zl) = ZIPLIST_HEADER_SIZE;
     ZIPLIST_LENGTH(zl) = 0;
 
 /* Resize the ziplist. */
 static unsigned char *ziplistResize(unsigned char *zl, unsigned int len) {
-    zl = zrealloc(zl,len);
+    zl = zrealloc2(zl,len);
     ZIPLIST_BYTES(zl) = len;
     zl[len-1] = ZIP_END;
     return zl;

File src/zipmap.c

 
 /* Create a new empty zipmap. */
 unsigned char *zipmapNew(void) {
-    unsigned char *zm = zmalloc(2);
+    unsigned char *zm = zmalloc2(2);
 
     zm[0] = 0; /* Length */
     zm[1] = ZIPMAP_END;
 }
 
 static inline unsigned char *zipmapResize(unsigned char *zm, unsigned int len) {
-    zm = zrealloc(zm, len);
+    zm = zrealloc2(zm, len);
     zm[len-1] = ZIPMAP_END;
     return zm;
 }

File src/zmalloc.c

     return p;
 }
 
+/* Return the allocation size when using zmalloc2() function.
+ * For requests <= 2, 2 is returned.
+ * If the allocation requested is SIZE_MAX, SIZE_MAX itself is returned.
+ * Otherwise the next power of two >= val is returned. */
+size_t zmalloc2AllocSize(size_t val) {
+    if (val <= 2) return 2;
+    if (val == (size_t)-1) return (size_t)-1;
+    val--;
+    val = (val >> 1) | val;
+    val = (val >> 2) | val;
+    val = (val >> 4) | val;
+    val = (val >> 8) | val;
+    val = (val >> 16) | val;
+    val = (val >> 32) | val;
+    return val+1;
+}
+
+void *zmalloc2(size_t size) {
+    return zmalloc(zmalloc2AllocSize(size));
+}
+
+void *zcalloc2(size_t size) {
+    return zcalloc(zmalloc2AllocSize(size));
+}
+
+void *zrealloc2(void *ptr, size_t size) {
+    return zrealloc(ptr,zmalloc2AllocSize(size));
+}
+
 size_t zmalloc_used_memory(void) {
     size_t um;
 
     zmalloc_thread_safe = 1;
 }
 
+
+
 /* Get the RSS information in an OS-specific way.
  *
  * WARNING: the function zmalloc_get_rss() is not designed to be fast

File src/zmalloc.h

 void *zmalloc(size_t size);
 void *zcalloc(size_t size);
 void *zrealloc(void *ptr, size_t size);
+void *zmalloc2(size_t size);
+void *zcalloc2(size_t size);
+void *zrealloc2(void *ptr, size_t size);
 void zfree(void *ptr);
 char *zstrdup(const char *s);
 size_t zmalloc_used_memory(void);