Command processing

Roy Lyseng Roy.Lyseng at Sun.COM
Mon Mar 10 15:09:51 UTC 2008



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


More information about the memcached mailing list