Command processing
marc at corky.net
marc at corky.net
Mon Mar 10 15:41:16 UTC 2008
Roy Lyseng wrote:
In reality, a full blown string compare is not even needed in this
case. One can loop through the command array comparing the first
character only, then the second, etc.
If the actual length of the command is stored in the array as well and
the length of the requested command is done beforehand, one needs to at
most only compare two characters and the length.
From a quick look only the get/gets commands both start with the same
two characters - therefore the length must also be compared. Otherwise
the entire string in this particular case.
I could also argue that 'add' is almost certainly less frequency in most
people's apps than 'set'.
In reality, we're nit-picking too much, a few tens/hundreds of clock
cycles more or less per request would not give us any meaningful
performance benefit. Interrupts and context switches are the
bottlenecks when demand is extremely high - tens of thousands of
requests per second.
Just for fun I started porting memcached into a kernel module with the
goal of measuring performance differences between the standard one and
the kernel module - but I haven't finished that yet. There would be
pretty large savings on context switching and interrupts - though I
don't think real world performance gains would be meaningful for 99% of
the users on this list. Only a few push (or get close to pushing)
memcached to its limits.
Marc
>
>
> 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
>
>
> !DSPAM:47d5500917066856617375!
>
More information about the memcached
mailing list