<HTML>
<HEAD>
<TITLE>Re: set_multi() and delete_multi()</TITLE>
</HEAD>
<BODY>
<FONT FACE="Verdana, Helvetica, Arial"><SPAN STYLE='font-size:12.0px'>In the latest libmemcache client I’ve implemented delete_multi. I haven’t done set_multi yet because internally we currently have little demand for it. With the new libmemcache design it wouldn’t be too hard to add. In the new API, there is only one mc_delete function. It takes a list of keys and an exptime for all of them. Delete request messages are built for all targeted servers and queued up for asynch transmission to the remote memcache daemon. Results are correlated with original request by order of arrival. That is the first result is assumed to be for the first request to that server, &c. Heterogeneous multi_* ops are not supported.<BR>
<BR>
set_multi is slightly more difficult if one wants to do keys with heterogeneous mixes of flags or exptimes. delete worked well because the typical use case is to specify only the key. I can easily imagine wanting to do set_multi with different flags. For example a php or python app needs to set an int value, a string value and a complex array. The first two wind up with flags == 0 and the last with flags == php or python serialized.<BR>
To support that means the set_multi will have to take a vector of set_message structs with key name, value, flags and exptime. Not a huge deal but it complicates the API. Unlike mc_delete or mc_get which basically are always multi-operations, there will probably have to be a separate mc_set and mc_set_multi, with the following signatures:<BR>
<BR>
int mc_set(mc_handle_t mc, const char* key, size_t nkey, const char* value, size_t nvalue, const uint16_t flags, const uint32_t exptime);<BR>
<BR>
typedef struct mc_update_req_s {<BR>
char* key;<BR>
size_t nkey;<BR>
char* value;<BR>
size_t nvalue;<BR>
uint16_t flags;<BR>
uint32_t exptime;<BR>
} mc_update_req_t;<BR>
<BR>
int mc_set_multi(mc_handle_t mc, const mc_update_req_t* reqs, const size_t nreqs);<BR>
<BR>
The same would apply for mc_add and mc_replace. Let me know what you think. Given that the mc_update_req_t vector only needs to exist for the scope of the call it shouldn’t be difficult for the extension code (ie php or python extension) to allocate the temporary space and initialized it prior to calling mc_set_multi, and freeing it on return.<BR>
<BR>
On 3/12/07 10:33 AM, "Steven Grimm" <sgrimm@facebook.com> wrote:<BR>
<BR>
</SPAN></FONT><BLOCKQUOTE><FONT SIZE="2"><FONT FACE="Monaco, Courier New"><SPAN STYLE='font-size:10.0px'>Not on the server side, no. (I can't speak for the client side; I'm not <BR>
the one working on that here.) We rarely do large batch deletes or sets, <BR>
so the meager CPU savings wouldn't be worth the engineering time for us.<BR>
<BR>
-Steve<BR>
<BR>
<BR>
Michael Monashev wrote:<BR>
> Hi Steven,<BR>
><BR>
> Do you plan to implement set_multi() and delete_multi() in the future?<BR>
><BR>
> SG> The server-side CPU cost of processing a two-key get request is MUCH<BR>
> SG> lower than processing two single-key requests because you only have to<BR>
> SG> run through the parser and (usually) the libevent code once. Don't<BR>
> SG> remember the exact ratio off the top of my head but it's pretty steep,<BR>
> SG> something in the neighborhood of a 10-key get request taking only 2x the<BR>
> SG> CPU time of a 1-key request.<BR>
><BR>
> SG> This would be less of an issue with a well-designed binary wire protocol<BR>
> SG> that didn't require any parsing at all (though you'd still see some<BR>
> SG> difference due to having to wake up for input on each request), but<BR>
> SG> right now you can save significant amounts of CPU time on the memcached<BR>
> SG> server by bundling your gets up into as few requests as possible. So I'm<BR>
> SG> glad multi-gets aren't just a series of streamed single-gets.<BR>
><BR>
> --<BR>
><BR>
> Michael<BR>
><BR>
> <BR>
<BR>
</SPAN></FONT></FONT></BLOCKQUOTE><FONT SIZE="2"><FONT FACE="Monaco, Courier New"><SPAN STYLE='font-size:10.0px'><BR>
</SPAN></FONT></FONT>
</BODY>
</HTML>