Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ endif

REDIS_SERVER_NAME=redis-server$(PROG_SUFFIX)
REDIS_SENTINEL_NAME=redis-sentinel$(PROG_SUFFIX)
REDIS_SERVER_OBJ=threads_mngr.o memory_prefetch.o adlist.o quicklist.o ae.o anet.o dict.o ebuckets.o eventnotifier.o iothread.o mstr.o kvstore.o fwtree.o estore.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o cluster_legacy.o cluster_slot_stats.o crc16.o endianconv.o slowlog.o eval.o bio.o rio.o rand.o memtest.o syscheck.o crcspeed.o crccombine.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o lolwut8.o acl.o tracking.o socket.o tls.o sha256.o timeout.o setcpuaffinity.o monotonic.o mt19937-64.o resp_parser.o call_reply.o script_lua.o script.o functions.o function_lua.o commands.o strl.o connection.o unix.o logreqres.o
REDIS_SERVER_OBJ=threads_mngr.o memory_prefetch.o adlist.o quicklist.o ae.o anet.o dict.o ebuckets.o eventnotifier.o iothread.o mstr.o kvstore.o fwtree.o estore.o server.o sds.o zmalloc.o lzf_c.o lzf_d.o pqsort.o zipmap.o sha1.o ziplist.o release.o networking.o util.o object.o db.o replication.o rdb.o t_string.o t_list.o t_set.o t_zset.o t_hash.o config.o aof.o pubsub.o multi.o debug.o sort.o intset.o syncio.o cluster.o cluster_legacy.o cluster_slot_stats.o crc16.o endianconv.o slowlog.o eval.o bio.o rio.o rand.o memtest.o syscheck.o crcspeed.o crccombine.o crc64.o bitops.o sentinel.o notify.o setproctitle.o blocked.o hyperloglog.o latency.o sparkline.o redis-check-rdb.o redis-check-aof.o geo.o lazyfree.o module.o evict.o expire.o geohash.o geohash_helper.o childinfo.o defrag.o siphash.o rax.o t_stream.o listpack.o localtime.o lolwut.o lolwut5.o lolwut6.o lolwut8.o acl.o tracking.o socket.o tls.o sha256.o timeout.o setcpuaffinity.o monotonic.o mt19937-64.o resp_parser.o call_reply.o script_lua.o script.o functions.o function_lua.o commands.o strl.o connection.o unix.o logreqres.o sobj.o
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated: add test module

REDIS_CLI_NAME=redis-cli$(PROG_SUFFIX)
REDIS_CLI_OBJ=anet.o adlist.o dict.o redis-cli.o zmalloc.o release.o ae.o redisassert.o crcspeed.o crccombine.o crc64.o siphash.o crc16.o monotonic.o cli_common.o mt19937-64.o strl.o cli_commands.o
REDIS_BENCHMARK_NAME=redis-benchmark$(PROG_SUFFIX)
Expand Down
1 change: 1 addition & 0 deletions src/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -3127,6 +3127,7 @@ standardConfig static_configs[] = {
createBoolConfig("hide-user-data-from-log", NULL, MODIFIABLE_CONFIG, server.hide_user_data_from_log, 0, NULL, NULL),
createBoolConfig("lazyexpire-nested-arbitrary-keys", NULL, MODIFIABLE_CONFIG | HIDDEN_CONFIG, server.lazyexpire_nested_arbitrary_keys, 1, NULL, NULL),
createBoolConfig("cluster-slot-stats-enabled", NULL, MODIFIABLE_CONFIG, server.cluster_slot_stats_enabled, 0, NULL, NULL),
createBoolConfig("shared-strings-enabled", NULL, IMMUTABLE_CONFIG | HIDDEN_CONFIG, server.shared_strings_enabled, 1, NULL, NULL),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think we can find a better name for this config

first we need to decide if we can see this feautre used in redis core or only for modules

in addition, since we are already adding this config, let's make use it - make sure it's a only-startup config and edit sobj.c and possibly module.c accordingly

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

basically it's a hint for data-type codepaths, to know if they should use shared-strings in ther implementations
the reason you don't see it in use in core is because no core data-type decided to perform this optimization (yet, perhaps it could be used in other string based data-types)

if the core decides this opt will never be relevant, than the "right" thing to do it to rem it here and add it only on our fork instead of creating some stub usage for that


/* String Configs */
createStringConfig("aclfile", NULL, IMMUTABLE_CONFIG, ALLOW_EMPTY_STRING, server.acl_filename, "", NULL, NULL),
Expand Down
48 changes: 29 additions & 19 deletions src/defrag.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,20 @@ typedef struct {
unsigned long cursor;
} defragModuleCtx;

/* Defrag helper for bare-bone allocation without freeing old pointer, and ignoring defrag hint. */
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@oranagra @moticless how are we feeling about the changes in defrag.c?

note that the purpose of these changes is to allow sobj_defrag to create a new sobj without using tcache (so basically we wouldn't need to touch defrag.c if we had dupStringObjectNoTcache)

if we think that anyway we would need these sorts of "defrag-no-free" changes in the future then all is good, but generally speaking, since the purpose is to duplicate an object without using tcache, maybe a better approach is to create "dup-no-tcache" functions in object.c)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question is if we think that allocating an object without using tcache is more of a defrag.c code or object.c

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think the reason to use NoTcache is defrag related, so i'm ok adding such capabilities to defrag.c

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that said... taking a look at the defrag.c modifications, IIRC i told @itayTziv that i think that just blindly duplicating all objects is the wrong approach.
@itayTziv do you remember the details from that conversation? IIRC you presented the reason you do that and i gave you an alternative.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main issue was with the possibility that robj will be defraged and sds will not. this could lead to robjA freeing an sds that's still in use by robjB. solution was to tie them together (if one's deffragged, so must the other..).
I also raised concern that if we don't defrag all, at the end of the full-cycle we'll have duplicate memory we continue to run with. you said it's ok and can wait for the next defrag triggered

on another note - after rediscussing with @inbaryuval and @guybe7 we decided to not add the feature to OSS yet, because of other features that redis supports (like async-flush) or will support (like ASM) that'll break the current implementation

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so are you going to do that (if one is duplicated, duplicate both, but if neither required being moved, don't move either)?

void* activeDefragAllocWithoutHint(void *ptr) {
size_t size;
void *newptr;
/* move this allocation to a new allocation.
* make sure not to use the thread cache. so that we don't get back the same
* pointers we try to free */
size = zmalloc_usable_size(ptr);
newptr = zmalloc_no_tcache(size);
memcpy(newptr, ptr, size);
server.stat_active_defrag_hits++;
return newptr;
}

/* this method was added to jemalloc in order to help us understand which
* pointers are worthwhile moving and which aren't */
int je_get_defrag_hint(void* ptr);
Expand All @@ -149,20 +163,11 @@ int je_get_defrag_hint(void* ptr);
* Note: The caller is responsible for freeing the old pointer if this function
* returns a non-NULL value. */
void* activeDefragAllocWithoutFree(void *ptr) {
size_t size;
void *newptr;
if(!je_get_defrag_hint(ptr)) {
server.stat_active_defrag_misses++;
return NULL;
}
/* move this allocation to a new allocation.
* make sure not to use the thread cache. so that we don't get back the same
* pointers we try to free */
size = zmalloc_usable_size(ptr);
newptr = zmalloc_no_tcache(size);
memcpy(newptr, ptr, size);
server.stat_active_defrag_hits++;
return newptr;
return activeDefragAllocWithoutHint(ptr);
}

void activeDefragFree(void *ptr) {
Expand Down Expand Up @@ -227,10 +232,10 @@ void activeDefragFreeRaw(void *ptr) {
*
* returns NULL in case the allocation wasn't moved.
* when it returns a non-null value, the old pointer was already released
* and should NOT be accessed. */
sds activeDefragSds(sds sdsptr) {
* and should NOT be accessed (unless duplicate was specified). */
sds activeDefragSdsLogic(sds sdsptr, int duplicate) {
void* ptr = sdsAllocPtr(sdsptr);
void* newptr = activeDefragAlloc(ptr);
void* newptr = duplicate ? activeDefragAllocWithoutHint(ptr) : activeDefragAlloc(ptr);
if (newptr) {
size_t offset = sdsptr - (char*)ptr;
sdsptr = (char*)newptr + offset;
Expand All @@ -239,6 +244,10 @@ sds activeDefragSds(sds sdsptr) {
return NULL;
}

sds activeDefragSds(sds sdsptr) {
return activeDefragSdsLogic(sdsptr, 0);
}

/* Defrag helper for hfield strings
*
* returns NULL in case the allocation wasn't moved.
Expand Down Expand Up @@ -284,30 +293,31 @@ void *activeDefragHfieldAndUpdateRef(void *ptr, void *privdata) {
* reference count is not 1, in these cases, the caller must explicitly pass
* in the reference count, otherwise defragmentation will not be performed.
* Note that the caller is responsible for updating any other references to the robj. */
robj *activeDefragStringObEx(robj* ob, int expected_refcount) {
robj *activeDefragStringObEx(robj* ob, int expected_refcount, int duplicate) {
void* (*defragAllocator)(void*) = duplicate ? activeDefragAllocWithoutHint : activeDefragAlloc;
robj *ret = NULL;
if (ob->refcount!=expected_refcount)
return NULL;

/* try to defrag robj (only if not an EMBSTR type (handled below). */
if (ob->type!=OBJ_STRING || ob->encoding!=OBJ_ENCODING_EMBSTR) {
if ((ret = activeDefragAlloc(ob))) {
if ((ret = defragAllocator(ob))) {
ob = ret;
}
}

/* try to defrag string object */
if (ob->type == OBJ_STRING) {
if(ob->encoding==OBJ_ENCODING_RAW) {
sds newsds = activeDefragSds((sds)ob->ptr);
sds newsds = activeDefragSdsLogic((sds)ob->ptr, duplicate);
if (newsds) {
ob->ptr = newsds;
}
} else if (ob->encoding==OBJ_ENCODING_EMBSTR) {
/* The sds is embedded in the object allocation, calculate the
* offset and update the pointer in the new allocation. */
long ofs = (intptr_t)ob->ptr - (intptr_t)ob;
if ((ret = activeDefragAlloc(ob))) {
if ((ret = defragAllocator(ob))) {
ret->ptr = (void*)((intptr_t)ret + ofs);
}
} else if (ob->encoding!=OBJ_ENCODING_INT) {
Expand All @@ -323,7 +333,7 @@ robj *activeDefragStringObEx(robj* ob, int expected_refcount) {
* when it returns a non-null value, the old pointer was already released
* and should NOT be accessed. */
robj *activeDefragStringOb(robj* ob) {
return activeDefragStringObEx(ob, 1);
return activeDefragStringObEx(ob, 1, 0);
}

/* Defrag helper for lua scripts
Expand Down Expand Up @@ -1095,7 +1105,7 @@ void defragPubsubScanCallback(void *privdata, const dictEntry *de, dictEntryLink

/* Try to defrag the channel name. */
serverAssert(channel->refcount == (int)dictSize(clients) + 1);
newchannel = activeDefragStringObEx(channel, dictSize(clients) + 1);
newchannel = activeDefragStringObEx(channel, dictSize(clients) + 1, 0);
if (newchannel) {
kvstoreDictSetKey(pubsub_channels, ctx->kvstate.slot, (dictEntry*)de, newchannel);

Expand Down
5 changes: 5 additions & 0 deletions src/dict.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,6 +704,11 @@ void dictFreeUnlinkedEntry(dict *d, dictEntry *he) {
if (!entryIsKey(he)) zfree(decodeMaskedPtr(he));
}

void dictFreeUnlinkedEntryOnly(dictEntry *he) {
if (he == NULL) return;
if (!entryIsKey(he)) zfree(decodeMaskedPtr(he));
}

/* Destroy an entire dictionary */
int _dictClear(dict *d, int htidx, void(callback)(dict*)) {
unsigned long i;
Expand Down
1 change: 1 addition & 0 deletions src/dict.h
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ int dictReplace(dict *d, void *key, void *val);
int dictDelete(dict *d, const void *key);
dictEntry *dictUnlink(dict *d, const void *key);
void dictFreeUnlinkedEntry(dict *d, dictEntry *he);
void dictFreeUnlinkedEntryOnly(dictEntry *he);
dictEntryLink dictTwoPhaseUnlinkFind(dict *d, const void *key, int *table_index);
void dictTwoPhaseUnlinkFree(dict *d, dictEntryLink llink, int table_index);
void dictRelease(dict *d);
Expand Down
35 changes: 35 additions & 0 deletions src/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
#include "call_reply.h"
#include "hdr_histogram.h"
#include "crc16_slottable.h"
#include "sobj.h"
#include <dlfcn.h>
#include <sys/stat.h>
#include <sys/wait.h>
Expand Down Expand Up @@ -380,6 +381,10 @@ typedef struct RedisModuleConfigIterator {
int is_glob; /* Is the pattern a glob-pattern or a fixed string? */
} RedisModuleConfigIterator;

typedef struct RedisModulePool {
dict *pool; /* Intern pool of same-group objects. Implemented over a lookup-set (dict w/ `.no_value = 1`) */
} RedisModulePool;

/* Flags for moduleCreateArgvFromUserFormat(). */
#define REDISMODULE_ARGV_REPLICATE (1<<0)
#define REDISMODULE_ARGV_NO_AOF (1<<1)
Expand Down Expand Up @@ -2650,6 +2655,31 @@ RedisModuleString *RM_CreateString(RedisModuleCtx *ctx, const char *ptr, size_t
return o;
}

RedisModulePool *RM_CreateSharePool(void) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we really need several of these pools? maybe there should be only one pool, where all modules (and possibly redis core) save their shared strings to

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

even if we do decide to have several pools (let's say one for each module and one for redis core) i think that the pool (dict) should be created on module initialization and kept within the struct RedisModule

so the API should be

RM_CreateSharedString(const char *ptr, size_t len) RM_FreeSharedString(RedisModuleString *str) RM_DefragSharedString(RedisModuleDefragCtx *ctx, RedisModuleString *str) 
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe we should even be more explicit and define a new type RedisModuleSharedString

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are pros and cons for mono/multi-pool approaches. for e.g. single pool will have larger refcounts, which means longer time to defrag (in which 2 copies are sustained...). you may chose your approach
regarding your suggestions - just yesterday I was talking to @moticless and he was worried the existing API will be too specific and tailored to specific use case. I believe it's actually very generic, but the above mentioned suggestions certainly drive it in this direction (which OSS seems to dislike).
e.g. RedisModuleSharedString couldn't be used with any of the other RMS APIs? why?
what if I want RedisModule with 2 pools? or a single pool shared between two of my modules?

please note the repeating argument is that you could functionally perform any of your suggestions with the existing API, whilst also being able to do other things we don't think on currently

RedisModulePool *pool = zmalloc(sizeof(*pool));
pool->pool = sobj_init();

return pool;
}

void RM_ReleaseSharePool(RedisModulePool *pool) {
sobj_release(pool->pool);
zfree(pool);
}

RedisModuleString *RM_CreateSharedString(const char *ptr, size_t len, RedisModulePool *pool) {
return (RedisModuleString*)sobj_new(ptr, len, pool->pool);
}

void RM_FreeSharedString(RedisModuleString *str, RedisModulePool *pool) {
sobj_free((sobj*)str, pool->pool);
}

RedisModuleString *RM_DefragRedisModuleSharedString(RedisModuleDefragCtx *ctx, RedisModuleString *str, RedisModulePool *pool) {
UNUSED(ctx);
return (RedisModuleString*)sobj_defrag((sobj*)str, pool->pool);
}

/* Create a new module string object from a printf format and arguments.
* The returned string must be freed with RedisModule_FreeString(), unless
* automatic memory is enabled.
Expand Down Expand Up @@ -14640,6 +14670,10 @@ void moduleRegisterCoreAPI(void) {
REGISTER_API(CreateStringFromStreamID);
REGISTER_API(CreateStringPrintf);
REGISTER_API(FreeString);
REGISTER_API(CreateSharePool);
REGISTER_API(ReleaseSharePool);
REGISTER_API(CreateSharedString);
REGISTER_API(FreeSharedString);
REGISTER_API(StringPtrLen);
REGISTER_API(AutoMemory);
REGISTER_API(Replicate);
Expand Down Expand Up @@ -14897,6 +14931,7 @@ void moduleRegisterCoreAPI(void) {
REGISTER_API(DefragAllocRaw);
REGISTER_API(DefragFreeRaw);
REGISTER_API(DefragRedisModuleString);
REGISTER_API(DefragRedisModuleSharedString);
REGISTER_API(DefragRedisModuleDict);
REGISTER_API(DefragShouldStop);
REGISTER_API(DefragCursorSet);
Expand Down
11 changes: 11 additions & 0 deletions src/redismodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,7 @@ typedef struct RedisModuleUser RedisModuleUser;
typedef struct RedisModuleKeyOptCtx RedisModuleKeyOptCtx;
typedef struct RedisModuleRdbStream RedisModuleRdbStream;
typedef struct RedisModuleConfigIterator RedisModuleConfigIterator;
typedef struct RedisModulePool RedisModulePool;

typedef int (*RedisModuleCmdFunc)(RedisModuleCtx *ctx, RedisModuleString **argv, int argc);
typedef void (*RedisModuleDisconnectFunc)(RedisModuleCtx *ctx, RedisModuleBlockedClient *bc);
Expand Down Expand Up @@ -1034,6 +1035,10 @@ REDISMODULE_API RedisModuleString * (*RedisModule_CreateStringFromString)(RedisM
REDISMODULE_API RedisModuleString * (*RedisModule_CreateStringFromStreamID)(RedisModuleCtx *ctx, const RedisModuleStreamID *id) REDISMODULE_ATTR;
REDISMODULE_API RedisModuleString * (*RedisModule_CreateStringPrintf)(RedisModuleCtx *ctx, const char *fmt, ...) REDISMODULE_ATTR_PRINTF(2,3) REDISMODULE_ATTR;
REDISMODULE_API void (*RedisModule_FreeString)(RedisModuleCtx *ctx, RedisModuleString *str) REDISMODULE_ATTR;
REDISMODULE_API RedisModulePool * (*RedisModule_CreateSharePool)(void) REDISMODULE_ATTR;
REDISMODULE_API void (*RedisModule_ReleaseSharePool)(RedisModulePool *pool) REDISMODULE_ATTR;
REDISMODULE_API RedisModuleString * (*RedisModule_CreateSharedString)(const char *ptr, size_t len, RedisModulePool *pool) REDISMODULE_ATTR;
REDISMODULE_API void (*RedisModule_FreeSharedString)(RedisModuleString *str, RedisModulePool *pool) REDISMODULE_ATTR;
REDISMODULE_API const char * (*RedisModule_StringPtrLen)(const RedisModuleString *str, size_t *len) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_ReplyWithError)(RedisModuleCtx *ctx, const char *err) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_ReplyWithErrorFormat)(RedisModuleCtx *ctx, const char *fmt, ...) REDISMODULE_ATTR;
Expand Down Expand Up @@ -1324,6 +1329,7 @@ REDISMODULE_API void *(*RedisModule_DefragAlloc)(RedisModuleDefragCtx *ctx, void
REDISMODULE_API void *(*RedisModule_DefragAllocRaw)(RedisModuleDefragCtx *ctx, size_t size) REDISMODULE_ATTR;
REDISMODULE_API void (*RedisModule_DefragFreeRaw)(RedisModuleDefragCtx *ctx, void *ptr) REDISMODULE_ATTR;
REDISMODULE_API RedisModuleString *(*RedisModule_DefragRedisModuleString)(RedisModuleDefragCtx *ctx, RedisModuleString *str) REDISMODULE_ATTR;
REDISMODULE_API RedisModuleString *(*RedisModule_DefragRedisModuleSharedString)(RedisModuleDefragCtx *ctx, RedisModuleString *str, RedisModulePool *pool) REDISMODULE_ATTR;
REDISMODULE_API RedisModuleDict *(*RedisModule_DefragRedisModuleDict)(RedisModuleDefragCtx *ctx, RedisModuleDict *dict, RedisModuleDefragDictValueCallback valueCB, RedisModuleString **seekTo) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_DefragShouldStop)(RedisModuleDefragCtx *ctx) REDISMODULE_ATTR;
REDISMODULE_API int (*RedisModule_DefragCursorSet)(RedisModuleDefragCtx *ctx, unsigned long cursor) REDISMODULE_ATTR;
Expand Down Expand Up @@ -1455,6 +1461,10 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API(CreateStringFromStreamID);
REDISMODULE_GET_API(CreateStringPrintf);
REDISMODULE_GET_API(FreeString);
REDISMODULE_GET_API(CreateSharePool);
REDISMODULE_GET_API(ReleaseSharePool);
REDISMODULE_GET_API(CreateSharedString);
REDISMODULE_GET_API(FreeSharedString);
REDISMODULE_GET_API(StringPtrLen);
REDISMODULE_GET_API(AutoMemory);
REDISMODULE_GET_API(Replicate);
Expand Down Expand Up @@ -1712,6 +1722,7 @@ static int RedisModule_Init(RedisModuleCtx *ctx, const char *name, int ver, int
REDISMODULE_GET_API(DefragAllocRaw);
REDISMODULE_GET_API(DefragFreeRaw);
REDISMODULE_GET_API(DefragRedisModuleString);
REDISMODULE_GET_API(DefragRedisModuleSharedString);
REDISMODULE_GET_API(DefragRedisModuleDict);
REDISMODULE_GET_API(DefragShouldStop);
REDISMODULE_GET_API(DefragCursorSet);
Expand Down
6 changes: 6 additions & 0 deletions src/server.h
Original file line number Diff line number Diff line change
Expand Up @@ -1930,6 +1930,7 @@ struct redisServer {
long long stat_cluster_incompatible_ops; /* Number of operations that are incompatible with cluster mode */
long long stat_total_prefetch_entries; /* Total number of prefetched dict entries */
long long stat_total_prefetch_batches; /* Total number of prefetched batches */
long long stat_shared_objects_cnt; /* Total number of pool-shared objects */
/* The following two are used to track instantaneous metrics, like
* number of operations per second, network traffic. */
struct {
Expand Down Expand Up @@ -1987,6 +1988,7 @@ struct redisServer {
unsigned int max_new_conns_per_cycle; /* The maximum number of tcp connections that will be accepted during each invocation of the event loop. */
int cluster_compatibility_sample_ratio; /* Sampling ratio for cluster mode incompatible commands. */
int lazyexpire_nested_arbitrary_keys; /* If disabled, avoid lazy-expire from commands that touch arbitrary keys (SCAN/RANDOMKEY) within transactions */
int shared_strings_enabled; /* Dictates whether to use shared-strings when possible */

/* AOF persistence */
int aof_enabled; /* AOF configuration */
Expand Down Expand Up @@ -3407,8 +3409,10 @@ int setOOMScoreAdj(int process_class);
void rejectCommandFormat(client *c, const char *fmt, ...);
void *activeDefragAlloc(void *ptr);
void *activeDefragAllocRaw(size_t size);
void activeDefragFree(void *ptr);
void activeDefragFreeRaw(void *ptr);
robj *activeDefragStringOb(robj* ob);
robj *activeDefragStringObEx(robj* ob, int expected_refcount, int duplicate);
void dismissSds(sds s);
void dismissMemory(void* ptr, size_t size_hint);
void dismissMemoryInChild(void);
Expand Down Expand Up @@ -3863,6 +3867,8 @@ int performEvictions(void);
void startEvictionTimeProc(void);

/* Keys hashing / comparison functions for dict.c hash tables. */
int dictObjKeyCompare(dictCmpCache *cache, const void *key1, const void *key2);
uint64_t dictObjHash(const void *key);
uint64_t dictSdsHash(const void *key);
uint64_t dictPtrHash(const void *key);
uint64_t dictSdsCaseHash(const void *key);
Expand Down
Loading
Loading