提交 ae22bf1e 编写于 作者: A antirez

Reclaim space from the client querybuf if needed.

上级 739803c0
...@@ -287,6 +287,7 @@ struct redisClient *createFakeClient(void) { ...@@ -287,6 +287,7 @@ struct redisClient *createFakeClient(void) {
selectDb(c,0); selectDb(c,0);
c->fd = -1; c->fd = -1;
c->querybuf = sdsempty(); c->querybuf = sdsempty();
c->querybuf_peak = 0;
c->argc = 0; c->argc = 0;
c->argv = NULL; c->argv = NULL;
c->bufpos = 0; c->bufpos = 0;
......
...@@ -43,6 +43,7 @@ redisClient *createClient(int fd) { ...@@ -43,6 +43,7 @@ redisClient *createClient(int fd) {
c->fd = fd; c->fd = fd;
c->bufpos = 0; c->bufpos = 0;
c->querybuf = sdsempty(); c->querybuf = sdsempty();
c->querybuf_peak = 0;
c->reqtype = 0; c->reqtype = 0;
c->argc = 0; c->argc = 0;
c->argv = NULL; c->argv = NULL;
...@@ -998,6 +999,7 @@ void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) { ...@@ -998,6 +999,7 @@ void readQueryFromClient(aeEventLoop *el, int fd, void *privdata, int mask) {
} }
qblen = sdslen(c->querybuf); qblen = sdslen(c->querybuf);
if (c->querybuf_peak < qblen) c->querybuf_peak = qblen;
c->querybuf = sdsMakeRoomFor(c->querybuf, readlen); c->querybuf = sdsMakeRoomFor(c->querybuf, readlen);
nread = read(fd, c->querybuf+qblen, readlen); nread = read(fd, c->querybuf+qblen, readlen);
if (nread == -1) { if (nread == -1) {
......
...@@ -642,7 +642,7 @@ long long getOperationsPerSecond(void) { ...@@ -642,7 +642,7 @@ long long getOperationsPerSecond(void) {
} }
void clientsCronHandleTimeout(redisClient *c) { void clientsCronHandleTimeout(redisClient *c) {
time_t now = time(NULL); time_t now = server.unixtime;
if (server.maxidletime && if (server.maxidletime &&
!(c->flags & REDIS_SLAVE) && /* no timeout for slaves */ !(c->flags & REDIS_SLAVE) && /* no timeout for slaves */
...@@ -662,15 +662,40 @@ void clientsCronHandleTimeout(redisClient *c) { ...@@ -662,15 +662,40 @@ void clientsCronHandleTimeout(redisClient *c) {
} }
} }
/* The client query buffer is an sds.c string that can end with a lot of
* free space not used, this function reclaims space if needed. */
void clientsCronResizeQueryBuffer(redisClient *c) {
size_t querybuf_size = sdsAllocSize(c->querybuf);
time_t idletime = server.unixtime - c->lastinteraction;
/* There are two conditions to resize the query buffer:
* 1) Query buffer is > BIG_ARG and too big for latest peak.
* 2) Client is inactive and the buffer is bigger than 1k. */
if (((querybuf_size > REDIS_MBULK_BIG_ARG) &&
(querybuf_size/(c->querybuf_peak+1)) > 2) ||
(querybuf_size > 1024 && idletime > 2))
{
/* Only resize the query buffer if it is actually wasting space. */
if (sdsavail(c->querybuf) > 1024) {
c->querybuf = sdsRemoveFreeSpace(c->querybuf);
}
}
/* Reset the peak again to capture the peak memory usage in the next
* cycle. */
c->querybuf_peak = 0;
}
void clientsCron(void) { void clientsCron(void) {
/* Make sure to process at least 1/100 of clients per call. /* Make sure to process at least 1/100 of clients per call.
* Since this function is called 10 times per second we are sure that * Since this function is called 10 times per second we are sure that
* in the worst case we process all the clients in 10 seconds. * in the worst case we process all the clients in 10 seconds.
* In normal conditions (a reasonable number of clients) we process * In normal conditions (a reasonable number of clients) we process
* all the clients in a shorter time. */ * all the clients in a shorter time. */
int iterations = listLength(server.clients)/100; int numclients = listLength(server.clients);
if (iterations < 50) iterations = 50; int iterations = numclients/100;
if (iterations < 50)
iterations = (numclients < 50) ? numclients : 50;
while(listLength(server.clients) && iterations--) { while(listLength(server.clients) && iterations--) {
redisClient *c; redisClient *c;
listNode *head; listNode *head;
...@@ -682,6 +707,7 @@ void clientsCron(void) { ...@@ -682,6 +707,7 @@ void clientsCron(void) {
head = listFirst(server.clients); head = listFirst(server.clients);
c = listNodeValue(head); c = listNodeValue(head);
clientsCronHandleTimeout(c); clientsCronHandleTimeout(c);
clientsCronResizeQueryBuffer(c);
} }
} }
......
...@@ -323,6 +323,7 @@ typedef struct redisClient { ...@@ -323,6 +323,7 @@ typedef struct redisClient {
redisDb *db; redisDb *db;
int dictid; int dictid;
sds querybuf; sds querybuf;
size_t querybuf_peak; /* Recent (100ms or more) peak of querybuf size */
int argc; int argc;
robj **argv; robj **argv;
struct redisCommand *cmd, *lastcmd; struct redisCommand *cmd, *lastcmd;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册