Skip to content

Commit

Permalink
Add zfree_with_size
Browse files Browse the repository at this point in the history
zfree updates memory statistics. It gets the size of the buffer from
jemalloc by calling zmalloc_size. This operation is costly. We can
avoid it if we know the buffer size. For example, we can calculate
size of sds from the data we have in its header.

This commit introduces zfree_with_size function that accepts both
pointer to a buffer, and its size. zfree is refactored to call
zfree_with_size.

sdsfree uses the new interface for all but SDS_TYPE_5.

Signed-off-by: Vadym Khoptynets <vadymkh@amazon.com>
  • Loading branch information
poiuj committed May 7, 2024
1 parent ba9dd7b commit 35924f9
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 11 deletions.
8 changes: 7 additions & 1 deletion src/sds.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,13 @@ sds sdsdup(const sds s) {
/* Free an sds string. No operation is performed if 's' is NULL. */
void sdsfree(sds s) {
if (s == NULL) return;
s_free((char*)s-sdsHdrSize(s[-1]));

/* SDS_TYPE_5 header doesn't contain the size of the allocation */
if ((s[-1] & SDS_TYPE_MASK) == SDS_TYPE_5) {
s_free(sdsAllocPtr(s));
} else {
s_free_with_size(sdsAllocPtr(s), sdsAllocSize(s));
}
}

/* Set the sds string length to the length as obtained with strlen(), so
Expand Down
1 change: 1 addition & 0 deletions src/sdsalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#define s_trymalloc ztrymalloc
#define s_tryrealloc ztryrealloc
#define s_free zfree
#define s_free_with_size zfree_with_size
#define s_malloc_usable zmalloc_usable
#define s_realloc_usable zrealloc_usable
#define s_trymalloc_usable ztrymalloc_usable
Expand Down
31 changes: 21 additions & 10 deletions src/zmalloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,22 +363,33 @@ size_t zmalloc_usable_size(void *ptr) {
}
#endif

void zfree(void *ptr) {
#ifndef HAVE_MALLOC_SIZE
void *realptr;
size_t oldsize;
/* Frees the memory buffer pointed by ptr and updates statistics.
* ptr must already point to the start of the buffer. On systems where we store
* an additional header, the caller must do the necessary adjustments.
* ptr must not be NULL. With jemalloc this fucntion uses the fast track by
* specifying the buffer size */
void zfree_with_size(void *ptr, size_t size) {
update_zmalloc_stat_free(size);

#ifdef USE_JEMALLOC
je_sdallocx(ptr, size, 0);
#else
free(ptr);
#endif
}

void zfree(void *ptr) {
if (ptr == NULL) return;

#ifdef HAVE_MALLOC_SIZE
update_zmalloc_stat_free(zmalloc_size(ptr));
free(ptr);
size_t size = zmalloc_size(ptr);
#else
realptr = (char*)ptr-PREFIX_SIZE;
oldsize = *((size_t*)realptr);
update_zmalloc_stat_free(oldsize+PREFIX_SIZE);
free(realptr);
ptr = (char*)ptr-PREFIX_SIZE;
size_t data_size = *((size_t*)ptr);
size_t size = data_size+PREFIX_SIZE;
#endif

zfree_with_size(ptr, size);
}

/* Similar to zfree, '*usable' is set to the usable size being freed. */
Expand Down
1 change: 1 addition & 0 deletions src/zmalloc.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ __attribute__((malloc,alloc_size(1),noinline)) void *ztrymalloc(size_t size);
__attribute__((malloc,alloc_size(1),noinline)) void *ztrycalloc(size_t size);
__attribute__((alloc_size(2),noinline)) void *ztryrealloc(void *ptr, size_t size);
void zfree(void *ptr);
void zfree_with_size(void *ptr, size_t size);
void *zmalloc_usable(size_t size, size_t *usable);
void *zcalloc_usable(size_t size, size_t *usable);
void *zrealloc_usable(void *ptr, size_t size, size_t *usable);
Expand Down

0 comments on commit 35924f9

Please sign in to comment.