Håkan Waara wrote:
I haven't hacked this code myself, so forgive me if I'm totally wrong, but couldn't you use a hash table instead below to avoid any string comparison at all?

I certainly could, but I do not think this is a performance pain point.

But the array of command strings would be a great start for another optimization.

Roy

/Håkan

Roy Lyseng wrote:
Hi,

I have been looking at structuring the command processing in memcached slightly.

I am thinking about creating an array with info about available commands:

static struct {
    char *cmdword;    /* Command word string */
    int   cmd;        /* Command shorthand */
    int   mintokens;  /* Minimum number of tokens (required) */
int maxtokens; /* Maximum number of tokens (zero means no limit) */
} cmds[] = {
   {"get",        CMD_GET,       3, 0},
   {"delete",     CMD_DELETE,    3, 5},
   {"add",        CMD_ADD,       6, 7},
   {"set",        CMD_SET,       6, 7},
   {"replace",    CMD_REPLACE,   6, 7},
   {"prepend",    CMD_PREPEND,   6, 7},
   {"append",     CMD_APPEND,    6, 7},
   {"gets",       CMD_GETS,      3, 0},
   {"cas",        CMD_CAS,       7, 8},
   {"incr",       CMD_INCR,      4, 5},
   {"decr",       CMD_DECR,      4, 5},
   {"bget",       CMD_BGET,      3, 0},
   {"own",        CMD_OWN,       3, 3},
   {"disown",     CMD_DISOWN,    3, 3},
   {"bg",         CMD_BG,        3, 3},
   {"stats",      CMD_STATS,     2, 0},
   {"flush_all",  CMD_FLUSH,     2, 4},
   {"version",    CMD_VERSION,   2, 2},
   {"quit",       CMD_QUIT,      2, 2},
{"slabs", CMD_SLABS, 5, 5}, /* Next token should be "reassign" */
   {"verbosity",  CMD_VERBOSITY, 3, 4},
{NULL, -1, 0, 0} /* Terminate with a NULL string pointer */
};

I have tried to sort the presumably most frequent commands first.

process_commands() will then do:

    ntokens = tokenize_command(command, tokens, MAX_TOKENS);

    for (i = 0; cmds[i].cmdword != NULL; i++) {
        if (strcmp(tokens[COMMAND_TOKEN].value, cmds[i].cmdword) == 0) {
           cmd = cmds[i].cmd;
           break;
        }
    }

    if (cmd < 0) {
        out_string(c, "ERROR");              /* Token not matched */
        return;
    }
    if (ntokens < cmds[i].mintokens ||
       (cmds[i].maxtokens > 0 && ntokens > cmds[i].maxtokens)) {
out_string(c, "ERROR"); /* Invalid number of tokens for this cmd */
        return;
    }

c->item_comm = cmd; /* Command being processed on connection */

    switch (cmd) {
    case CMD_GET:
    case CMD_BGET:
        process_get_command(c, tokens, ntokens, false);
        break;
...

Does this look interesting to you guys?

Before I go any further with this, is there any other information that should be used to characterize commands?

Are there commands that are not in use (BGET?)

More?

Thanks,
Roy

Reply via email to