Trond Norbye's Weblog

« Previous day (Jan 20, 2009) | Main | Next day (Jan 21, 2009) »

http://blogs.sun.com/trond/date/20090121 Wednesday January 21, 2009

noreply support in libmemcached - part two

In my previous post I described the implementation of noreply support in libmemcached, but Brian Aker commented that we should buffer the noreply packets as well to avoid sending a lot of packets over the wire.

Earlier today I pushed a patch that introduce a new function: memcached_return memcached_flush_buffers(memcached_st *).

So what does this mean for you as a developer? If we look at the following example:

  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1);
  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 1);
  for (int x= 0; x < 100; ++x) {
    char key[10];
    size_t len= sprintf(key, "%d", x);
    memcached_response ret;
    ret= memcached_set(memc, key, len, key, len, 0, 0);
    if (ret != MEMCACHED_SUCCESS && ret != MEMCACHED_BUFFERED)
      abort();
  }
  [ ... Perform application logic ... ]
  
  char* value= memcached_get(memc, key, strlen(key),
                             &value_length, &flags, &rc);

Without the patch I added today, libmemcached would send out the command to the server for each invocation of memcached_set. With the the patch I added today, all of the commands would be sent to the server in chunks when the user calls memcached_get. Now this doesn't buy us much from what we had before I added the noreply support (just that we don't have to parse the reply codes from the server). Well, lets talk about the new function I added today: memcached_flush_buffers. Let's look at some source:

  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BUFFER_REQUESTS, 1);
  memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_NOREPLY, 1);
  for (int x= 0; x < 100; ++x) {
    char key[10];
    size_t len= sprintf(key, "%d", x);
    memcached_response ret;
    ret= memcached_set(memc, key, len, key, len, 0, 0);
    if (ret != MEMCACHED_SUCCESS && ret != MEMCACHED_BUFFERED)
      abort();
  }
  
  if (memcached_flush_buffers(memc) != MEMCACHED_SUCCESS)
    abort();
  

  [ ... Perform application logic ... ]
  
  char* value= memcached_get(memc, key, strlen(key),
                             &value_length, &flags, &rc);

Now memcached_flush_buffers will send all of the commands in the buffers to the memcached servers, so that the memcached server may start executing them. This means that the memcached server may start processing the commands while we perform application logic. When we invoke memcached_get the memcached server may already be finish executing the commands in the buffer, and process the get request immediately.


Valid HTML! Valid CSS!

This is a personal weblog, I do not speak for my employer.