Stop using the freelist robj* cache
This commit is contained in:
parent
8df3dcada5
commit
a9b18e54d4
18
src/object.c
18
src/object.c
@ -3,22 +3,12 @@
|
|||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
robj *createObject(int type, void *ptr) {
|
robj *createObject(int type, void *ptr) {
|
||||||
robj *o;
|
robj *o = zmalloc(sizeof(*o));
|
||||||
|
|
||||||
if (server.vm_enabled) pthread_mutex_lock(&server.obj_freelist_mutex);
|
|
||||||
if (listLength(server.objfreelist)) {
|
|
||||||
listNode *head = listFirst(server.objfreelist);
|
|
||||||
o = listNodeValue(head);
|
|
||||||
listDelNode(server.objfreelist,head);
|
|
||||||
if (server.vm_enabled) pthread_mutex_unlock(&server.obj_freelist_mutex);
|
|
||||||
} else {
|
|
||||||
if (server.vm_enabled) pthread_mutex_unlock(&server.obj_freelist_mutex);
|
|
||||||
o = zmalloc(sizeof(*o));
|
|
||||||
}
|
|
||||||
o->type = type;
|
o->type = type;
|
||||||
o->encoding = REDIS_ENCODING_RAW;
|
o->encoding = REDIS_ENCODING_RAW;
|
||||||
o->ptr = ptr;
|
o->ptr = ptr;
|
||||||
o->refcount = 1;
|
o->refcount = 1;
|
||||||
|
|
||||||
/* Set the LRU to the current lruclock (minutes resolution).
|
/* Set the LRU to the current lruclock (minutes resolution).
|
||||||
* We do this regardless of the fact VM is active as LRU is also
|
* We do this regardless of the fact VM is active as LRU is also
|
||||||
* used for the maxmemory directive when Redis is used as cache.
|
* used for the maxmemory directive when Redis is used as cache.
|
||||||
@ -204,11 +194,7 @@ void decrRefCount(void *obj) {
|
|||||||
default: redisPanic("Unknown object type"); break;
|
default: redisPanic("Unknown object type"); break;
|
||||||
}
|
}
|
||||||
o->ptr = NULL; /* defensive programming. We'll see NULL in traces. */
|
o->ptr = NULL; /* defensive programming. We'll see NULL in traces. */
|
||||||
if (server.vm_enabled) pthread_mutex_lock(&server.obj_freelist_mutex);
|
|
||||||
if (listLength(server.objfreelist) > REDIS_OBJFREELIST_MAX ||
|
|
||||||
!listAddNodeHead(server.objfreelist,o))
|
|
||||||
zfree(o);
|
zfree(o);
|
||||||
if (server.vm_enabled) pthread_mutex_unlock(&server.obj_freelist_mutex);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
30
src/redis.c
30
src/redis.c
@ -616,10 +616,7 @@ int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
|
|||||||
while (server.vm_enabled && zmalloc_used_memory() >
|
while (server.vm_enabled && zmalloc_used_memory() >
|
||||||
server.vm_max_memory)
|
server.vm_max_memory)
|
||||||
{
|
{
|
||||||
int retval;
|
int retval = (server.vm_max_threads == 0) ?
|
||||||
|
|
||||||
if (tryFreeOneObjectFromFreelist() == REDIS_OK) continue;
|
|
||||||
retval = (server.vm_max_threads == 0) ?
|
|
||||||
vmSwapOneObjectBlocking() :
|
vmSwapOneObjectBlocking() :
|
||||||
vmSwapOneObjectThreaded();
|
vmSwapOneObjectThreaded();
|
||||||
if (retval == REDIS_ERR && !(loops % 300) &&
|
if (retval == REDIS_ERR && !(loops % 300) &&
|
||||||
@ -825,7 +822,6 @@ void initServer() {
|
|||||||
server.clients = listCreate();
|
server.clients = listCreate();
|
||||||
server.slaves = listCreate();
|
server.slaves = listCreate();
|
||||||
server.monitors = listCreate();
|
server.monitors = listCreate();
|
||||||
server.objfreelist = listCreate();
|
|
||||||
createSharedObjects();
|
createSharedObjects();
|
||||||
server.el = aeCreateEventLoop();
|
server.el = aeCreateEventLoop();
|
||||||
server.db = zmalloc(sizeof(redisDb)*server.dbnum);
|
server.db = zmalloc(sizeof(redisDb)*server.dbnum);
|
||||||
@ -1261,27 +1257,6 @@ void monitorCommand(redisClient *c) {
|
|||||||
|
|
||||||
/* ============================ Maxmemory directive ======================== */
|
/* ============================ Maxmemory directive ======================== */
|
||||||
|
|
||||||
/* Try to free one object form the pre-allocated objects free list.
|
|
||||||
* This is useful under low mem conditions as by default we take 1 million
|
|
||||||
* free objects allocated. On success REDIS_OK is returned, otherwise
|
|
||||||
* REDIS_ERR. */
|
|
||||||
int tryFreeOneObjectFromFreelist(void) {
|
|
||||||
robj *o;
|
|
||||||
|
|
||||||
if (server.vm_enabled) pthread_mutex_lock(&server.obj_freelist_mutex);
|
|
||||||
if (listLength(server.objfreelist)) {
|
|
||||||
listNode *head = listFirst(server.objfreelist);
|
|
||||||
o = listNodeValue(head);
|
|
||||||
listDelNode(server.objfreelist,head);
|
|
||||||
if (server.vm_enabled) pthread_mutex_unlock(&server.obj_freelist_mutex);
|
|
||||||
zfree(o);
|
|
||||||
return REDIS_OK;
|
|
||||||
} else {
|
|
||||||
if (server.vm_enabled) pthread_mutex_unlock(&server.obj_freelist_mutex);
|
|
||||||
return REDIS_ERR;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This function gets called when 'maxmemory' is set on the config file to limit
|
/* This function gets called when 'maxmemory' is set on the config file to limit
|
||||||
* the max memory used by the server, and we are out of memory.
|
* the max memory used by the server, and we are out of memory.
|
||||||
* This function will try to, in order:
|
* This function will try to, in order:
|
||||||
@ -1299,9 +1274,6 @@ void freeMemoryIfNeeded(void) {
|
|||||||
while (server.maxmemory && zmalloc_used_memory() > server.maxmemory) {
|
while (server.maxmemory && zmalloc_used_memory() > server.maxmemory) {
|
||||||
int j, k, freed = 0;
|
int j, k, freed = 0;
|
||||||
|
|
||||||
/* Basic strategy -- remove objects from the free list. */
|
|
||||||
if (tryFreeOneObjectFromFreelist() == REDIS_OK) continue;
|
|
||||||
|
|
||||||
for (j = 0; j < server.dbnum; j++) {
|
for (j = 0; j < server.dbnum; j++) {
|
||||||
long bestval = 0; /* just to prevent warning */
|
long bestval = 0; /* just to prevent warning */
|
||||||
sds bestkey = NULL;
|
sds bestkey = NULL;
|
||||||
|
@ -41,7 +41,6 @@
|
|||||||
#define REDIS_STATIC_ARGS 8
|
#define REDIS_STATIC_ARGS 8
|
||||||
#define REDIS_DEFAULT_DBNUM 16
|
#define REDIS_DEFAULT_DBNUM 16
|
||||||
#define REDIS_CONFIGLINE_MAX 1024
|
#define REDIS_CONFIGLINE_MAX 1024
|
||||||
#define REDIS_OBJFREELIST_MAX 1000000 /* Max number of objects to cache */
|
|
||||||
#define REDIS_MAX_SYNC_TIME 60 /* Slave can't take more to sync */
|
#define REDIS_MAX_SYNC_TIME 60 /* Slave can't take more to sync */
|
||||||
#define REDIS_EXPIRELOOKUPS_PER_CRON 10 /* lookup 10 expires per loop */
|
#define REDIS_EXPIRELOOKUPS_PER_CRON 10 /* lookup 10 expires per loop */
|
||||||
#define REDIS_MAX_WRITE_PER_EVENT (1024*64)
|
#define REDIS_MAX_WRITE_PER_EVENT (1024*64)
|
||||||
@ -366,7 +365,6 @@ struct redisServer {
|
|||||||
char neterr[ANET_ERR_LEN];
|
char neterr[ANET_ERR_LEN];
|
||||||
aeEventLoop *el;
|
aeEventLoop *el;
|
||||||
int cronloops; /* number of times the cron function run */
|
int cronloops; /* number of times the cron function run */
|
||||||
list *objfreelist; /* A list of freed objects to avoid malloc() */
|
|
||||||
time_t lastsave; /* Unix time of last save succeeede */
|
time_t lastsave; /* Unix time of last save succeeede */
|
||||||
/* Fields used only for stats */
|
/* Fields used only for stats */
|
||||||
time_t stat_starttime; /* server start time */
|
time_t stat_starttime; /* server start time */
|
||||||
@ -447,7 +445,6 @@ struct redisServer {
|
|||||||
list *io_processed; /* List of VM I/O jobs already processed */
|
list *io_processed; /* List of VM I/O jobs already processed */
|
||||||
list *io_ready_clients; /* Clients ready to be unblocked. All keys loaded */
|
list *io_ready_clients; /* Clients ready to be unblocked. All keys loaded */
|
||||||
pthread_mutex_t io_mutex; /* lock to access io_jobs/io_done/io_thread_job */
|
pthread_mutex_t io_mutex; /* lock to access io_jobs/io_done/io_thread_job */
|
||||||
pthread_mutex_t obj_freelist_mutex; /* safe redis objects creation/free */
|
|
||||||
pthread_mutex_t io_swapfile_mutex; /* So we can lseek + write */
|
pthread_mutex_t io_swapfile_mutex; /* So we can lseek + write */
|
||||||
pthread_attr_t io_threads_attr; /* attributes for threads creation */
|
pthread_attr_t io_threads_attr; /* attributes for threads creation */
|
||||||
int io_active_threads; /* Number of running I/O threads */
|
int io_active_threads; /* Number of running I/O threads */
|
||||||
@ -685,7 +682,6 @@ robj *dupStringObject(robj *o);
|
|||||||
robj *tryObjectEncoding(robj *o);
|
robj *tryObjectEncoding(robj *o);
|
||||||
robj *getDecodedObject(robj *o);
|
robj *getDecodedObject(robj *o);
|
||||||
size_t stringObjectLen(robj *o);
|
size_t stringObjectLen(robj *o);
|
||||||
int tryFreeOneObjectFromFreelist(void);
|
|
||||||
robj *createStringObjectFromLongLong(long long value);
|
robj *createStringObjectFromLongLong(long long value);
|
||||||
robj *createListObject(void);
|
robj *createListObject(void);
|
||||||
robj *createZiplistObject(void);
|
robj *createZiplistObject(void);
|
||||||
|
1
src/vm.c
1
src/vm.c
@ -96,7 +96,6 @@ void vmInit(void) {
|
|||||||
server.io_processed = listCreate();
|
server.io_processed = listCreate();
|
||||||
server.io_ready_clients = listCreate();
|
server.io_ready_clients = listCreate();
|
||||||
pthread_mutex_init(&server.io_mutex,NULL);
|
pthread_mutex_init(&server.io_mutex,NULL);
|
||||||
pthread_mutex_init(&server.obj_freelist_mutex,NULL);
|
|
||||||
pthread_mutex_init(&server.io_swapfile_mutex,NULL);
|
pthread_mutex_init(&server.io_swapfile_mutex,NULL);
|
||||||
server.io_active_threads = 0;
|
server.io_active_threads = 0;
|
||||||
if (pipe(pipefds) == -1) {
|
if (pipe(pipefds) == -1) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user