Skip to content

Commit 9253d85

Browse files
committed
Threaded lazyfree WIP redis#1.
1 parent 4d50d69 commit 9253d85

File tree

5 files changed

+36
-8
lines changed

5 files changed

+36
-8
lines changed

src/bio.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,8 @@ void *bioProcessBackgroundJobs(void *arg) {
185185
close((long)job->arg1);
186186
} else if (type == BIO_AOF_FSYNC) {
187187
aof_fsync((long)job->arg1);
188+
} else if (type == BIO_LAZY_FREE) {
189+
decrRefCount((robj*)job->arg1);
188190
} else {
189191
serverPanic("Wrong job type in bioProcessBackgroundJobs().");
190192
}

src/bio.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,5 @@ void bioKillThreads(void);
3838
/* Background job opcodes */
3939
#define BIO_CLOSE_FILE 0 /* Deferred close(2) syscall. */
4040
#define BIO_AOF_FSYNC 1 /* Deferred AOF fsync. */
41-
#define BIO_NUM_OPS 2
41+
#define BIO_LAZY_FREE 2 /* Deferred objects freeing. */
42+
#define BIO_NUM_OPS 3

src/lazyfree.c

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
#include "server.h"
2+
#include "bio.h"
3+
4+
static int lazyfree_threaded = 1; /* Use a thread to reclaim objects. */
25

36
/* Initialization of the lazy free engine. Must be called only once at server
47
* startup. */
@@ -97,7 +100,17 @@ size_t lazyfreeFastStep(void) {
97100

98101
/* Handles slow or fast collection steps. */
99102
size_t lazyfreeStep(int type) {
100-
if (type == LAZYFREE_STEP_FAST) return lazyfreeFastStep();
103+
/* Threaded implementaiton: only block for STEP_OOM. */
104+
if (lazyfree_threaded) {
105+
if (type == LAZYFREE_STEP_OOM)
106+
return bioWaitStepOfType(BIO_LAZY_FREE);
107+
return 0;
108+
}
109+
110+
/* Non threaded implementation: free things incrementally avoiding
111+
* to block. */
112+
if (type == LAZYFREE_STEP_FAST ||
113+
type == LAZYFREE_STEP_OOM) return lazyfreeFastStep();
101114

102115
size_t totalwork = 0;
103116
mstime_t end = mstime()+2;
@@ -130,8 +143,12 @@ int dbAsyncDelete(redisDb *db, robj *key) {
130143
/* If releasing the object is too much work, let's put it into the
131144
* lazy free list. */
132145
if (free_effort > LAZYFREE_THRESHOLD) {
133-
listAddNodeTail(server.lazyfree_obj,val);
134-
server.lazyfree_elements += free_effort;
146+
if (lazyfree_threaded) {
147+
bioCreateBackgroundJob(BIO_LAZY_FREE,val,NULL,NULL);
148+
} else {
149+
listAddNodeTail(server.lazyfree_obj,val);
150+
server.lazyfree_elements += free_effort;
151+
}
135152
dictSetVal(db->dict,de,NULL);
136153
}
137154
}
@@ -165,6 +182,9 @@ int lazyfreeCron(struct aeEventLoop *eventLoop, long long id, void *clientData)
165182
UNUSED(id);
166183
UNUSED(clientData);
167184

185+
/* Threaded lazy free does not need a timer, unregister the timer event. */
186+
if (lazyfree_threaded) return AE_NOMORE;
187+
168188
static size_t prev_mem;
169189
static int timer_period = 1000; /* Defauls to 1HZ */
170190
static double mem_trend = 0;

src/server.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3330,7 +3330,7 @@ int freeMemoryIfNeeded(void) {
33303330
latencyStartMonitor(eviction_latency);
33313331
while (mem_freed < mem_tofree) {
33323332
delta = (long long) zmalloc_used_memory();
3333-
size_t workdone = lazyfreeStep(LAZYFREE_STEP_FAST);
3333+
size_t workdone = lazyfreeStep(LAZYFREE_STEP_OOM);
33343334
delta -= (long long) zmalloc_used_memory();
33353335
mem_freed += delta;
33363336
if (!workdone) break; /* Lazy free list is empty. */

src/server.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,9 +1402,14 @@ void slotToKeyAdd(robj *key);
14021402
void slotToKeyDel(robj *key);
14031403
void slotToKeyFlush(void);
14041404

1405-
/* Lazy free */
1406-
#define LAZYFREE_STEP_SLOW 0
1407-
#define LAZYFREE_STEP_FAST 1
1405+
/* Lazy free. Note that SLOW and FAST are only useful when incremental
1406+
* lazy free is active. For threaded lazy free the actual freeing of objects
1407+
* happens in the background. Only STEP_OOM is used since it blocks waiting
1408+
* for the freeing thread to do some work before returning. */
1409+
#define LAZYFREE_STEP_SLOW 0 /* Take 1-2 milliseconds to reclaim memory. */
1410+
#define LAZYFREE_STEP_FAST 1 /* Free a few elements ASAP and return. */
1411+
#define LAZYFREE_STEP_OOM 2 /* Free a few elements at any cost if there
1412+
is something to free: we are out of memory */
14081413
int dbAsyncDelete(redisDb *db, robj *key);
14091414
void initLazyfreeEngine(void);
14101415
size_t lazyfreeStep(int type);

0 commit comments

Comments
 (0)