diff --git a/src/debug.c b/src/debug.c index 27bc481767..4bd560e040 100644 --- a/src/debug.c +++ b/src/debug.c @@ -426,8 +426,10 @@ void debugCommand(client *c) { "MALLCTL-STR []", " Get or set a malloc tuning string.", #endif - "OBJECT ", + "OBJECT [fast]", " Show low level info about `key` and associated value.", + " Some fields of the default behavior may be time consuming to fetch,", + " and `fast` can be passed to avoid fetching them.", "DROP-CLUSTER-PACKET-FILTER ", " Drop all packets that match the filtered type. Set to -1 allow all packets.", "CLOSE-CLUSTER-LINK-ON-PACKET-DROP <0|1>", @@ -604,11 +606,14 @@ void debugCommand(client *c) { } else if (!strcasecmp(c->argv[1]->ptr, "close-cluster-link-on-packet-drop") && c->argc == 3) { server.debug_cluster_close_link_on_packet_drop = atoi(c->argv[2]->ptr); addReply(c, shared.ok); - } else if (!strcasecmp(c->argv[1]->ptr, "object") && c->argc == 3) { + } else if (!strcasecmp(c->argv[1]->ptr, "object") && (c->argc == 3 || c->argc == 4)) { dictEntry *de; robj *val; char *strenc; + int fast = 0; + if (c->argc == 4 && !strcasecmp(c->argv[3]->ptr, "fast")) fast = 1; + if ((de = dbFind(c->db, c->argv[2]->ptr)) == NULL) { addReplyErrorObject(c, shared.nokeyerr); return; @@ -639,22 +644,25 @@ void debugCommand(client *c) { used = snprintf(nextra, remaining, " ql_compressed:%d", compressed); nextra += used; remaining -= used; - /* Add total uncompressed size */ - unsigned long sz = 0; - for (quicklistNode *node = ql->head; node; node = node->next) { - sz += node->sz; + if (!fast) { + /* Add total uncompressed size */ + unsigned long sz = 0; + for (quicklistNode *node = ql->head; node; node = node->next) { + sz += node->sz; + } + used = snprintf(nextra, remaining, " ql_uncompressed_size:%lu", sz); + nextra += used; + remaining -= used; } - used = snprintf(nextra, remaining, " ql_uncompressed_size:%lu", sz); - nextra += used; - remaining -= used; } - addReplyStatusFormat(c, - "Value at:%p refcount:%d " - "encoding:%s serializedlength:%zu " - "lru:%d lru_seconds_idle:%llu%s", - (void *)val, val->refcount, strenc, rdbSavedObjectLen(val, c->argv[2], c->db->id), - val->lru, estimateObjectIdleTime(val) / 1000, extra); + sds s = sdsempty(); + s = sdscatprintf(s, "Value at:%p refcount:%d encoding:%s", (void *)val, val->refcount, strenc); + if (!fast) s = sdscatprintf(s, " serializedlength:%zu", rdbSavedObjectLen(val, c->argv[2], c->db->id)); + s = sdscatprintf(s, " lru:%d lru_seconds_idle:%llu", val->lru, estimateObjectIdleTime(val) / 1000); + s = sdscatprintf(s, "%s", extra); + addReplyStatusLength(c, s, sdslen(s)); + sdsfree(s); } else if (!strcasecmp(c->argv[1]->ptr, "sdslen") && c->argc == 3) { dictEntry *de; robj *val;