.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Reinventing the wheel: libmc
panmiaocai@douban.com
Jan 23, 2015
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Outline
Wordplay
The memcached family
Why reinventing the new wheel
Bad things of libmemcached
Design a new memcached client
The ASCII protocol(get/set part)
Module Diagram
BufferWriter
BufferReader
Other parts
Lessons I learned
Tips
Great Toolchain
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Outline
Wordplay
The memcached family
Why reinventing the new wheel
Bad things of libmemcached
Design a new memcached client
The ASCII protocol(get/set part)
Module Diagram
BufferWriter
BufferReader
Other parts
Lessons I learned
Tips
Great Toolchain
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
The memcached family
▶ memcached (the memcached server-side software)
▶ memcache (typo and nickname)
▶ mc (nickname)
▶ libmemcached ( C/C++ client library)
▶ libmemcache (yet another C client library, DEAD since 2006)
▶ python-memcached (pure python client library)
▶ python-libmemcached (Cython client, library based on
libmemcached)
▶ cmemcached (alias of python-libmemcached)
▶ pylibmc (C-Extensions for Python by hand, based on
libmemcached)
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Outline
Wordplay
The memcached family
Why reinventing the new wheel
Bad things of libmemcached
Design a new memcached client
The ASCII protocol(get/set part)
Module Diagram
BufferWriter
BufferReader
Other parts
Lessons I learned
Tips
Great Toolchain
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Bad things of libmemcached
▶ Divergence of libmemcached between upstream and the
branch we use. (the “large split” feature)
▶ Complex
▶ Buggy
▶ (lib)memcached is a weird creature.
http://hoborglabs.com/en/blog/2013/memcached-php
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Outline
Wordplay
The memcached family
Why reinventing the new wheel
Bad things of libmemcached
Design a new memcached client
The ASCII protocol(get/set part)
Module Diagram
BufferWriter
BufferReader
Other parts
Lessons I learned
Tips
Great Toolchain
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Retrieval Commands
Request and Response
get <key>*rn
VALUE <key> <flags> <bytes>rn
<data block>rn
Example
get foo bar bazrn
VALUE foo 0 3rn
abcrn
VALUE baz 0 5rn
simp.rn
ENDrn
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Storage Commands
Request and Response
<key> <flags> <exptime> <bytes>rn
<data block>rn
STOREDrn | NOT STOREDrn
Example
set dou 0 0 10rn
0123456789rn
set ban 0 0 4rn
aoeirn
NOT STOREDrn
STOREDrn
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Outline
Wordplay
The memcached family
Why reinventing the new wheel
Bad things of libmemcached
Design a new memcached client
The ASCII protocol(get/set part)
Module Diagram
BufferWriter
BufferReader
Other parts
Lessons I learned
Tips
Great Toolchain
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Design of libmc
PyClient
|
Client
| (1:1)
ConnectionPool
| (1:N)
Connection
/ | (1:1) 
BufferReader Parser BufferWriter
| (1:N)
DataBlock
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Outline
Wordplay
The memcached family
Why reinventing the new wheel
Bad things of libmemcached
Design a new memcached client
The ASCII protocol(get/set part)
Module Diagram
BufferWriter
BufferReader
Other parts
Lessons I learned
Tips
Great Toolchain
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
BufferWriter
s s i z e t sendmsg ( i n t socket , const s t r u c t msghdr ∗
message , i n t f l a g s ) ;
s t r u c t i o v e c {
void ∗ i o v b a s e ;
s i z e t i o v l e n ;
};
s t r u c t msghdr {
. . .
s t r u c t i o v e c ∗ msg iov ;
s i z e t msg iovlen ;
. . .
};
▶ UIO MAXIOV
▶ commitRead
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Outline
Wordplay
The memcached family
Why reinventing the new wheel
Bad things of libmemcached
Design a new memcached client
The ASCII protocol(get/set part)
Module Diagram
BufferWriter
BufferReader
Other parts
Lessons I learned
Tips
Great Toolchain
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
BufferReader
+ Fixed + Flexible
+------------+------------+-----------------------+---------------
| 8192 recved| 8192 recved| more than 8192 recved | DataBlock ...
+----+----+-------+-------+---------------------------------------
|XXXX|OOOO|BB|BBBB|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC| DataBlockSlice
|XXXX|OOOO|BB|BBBB|CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC| ...
+------------+------+------------+------------+-------------------
|VALU|foo | 0 0 20| value of foo value of foo valu| Token
|E | | | e of foo .....................| ...
|----+----+-------+-------------------------------+---------------
▶ peek / readUntil / skipUtil / readUnsigned / readBytes /
skipBytes / (no rewind)
▶ token.size() in 0, 1, 2 / SmallVector
▶ predictive DataBlock size
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Outline
Wordplay
The memcached family
Why reinventing the new wheel
Bad things of libmemcached
Design a new memcached client
The ASCII protocol(get/set part)
Module Diagram
BufferWriter
BufferReader
Other parts
Lessons I learned
Tips
Great Toolchain
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Other parts
▶ Parser as a finite-state machine (FSM)
▶ poll in ConnectionPool
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Outline
Wordplay
The memcached family
Why reinventing the new wheel
Bad things of libmemcached
Design a new memcached client
The ASCII protocol(get/set part)
Module Diagram
BufferWriter
BufferReader
Other parts
Lessons I learned
Tips
Great Toolchain
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tips
▶ Prefer “switch statements” to if-else condition.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tips
▶ Prefer “switch statements” to if-else condition.
▶ “Exception” and “heap allocation” are slow in C++.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tips
▶ Prefer “switch statements” to if-else condition.
▶ “Exception” and “heap allocation” are slow in C++.
▶ Avoid memory copy.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tips
▶ Prefer “switch statements” to if-else condition.
▶ “Exception” and “heap allocation” are slow in C++.
▶ Avoid memory copy.
▶ SmallVector optimization.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tips
▶ Prefer “switch statements” to if-else condition.
▶ “Exception” and “heap allocation” are slow in C++.
▶ Avoid memory copy.
▶ SmallVector optimization.
▶ Undocumented “UIO MAXIOV” limit in iovec.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tips
▶ Prefer “switch statements” to if-else condition.
▶ “Exception” and “heap allocation” are slow in C++.
▶ Avoid memory copy.
▶ SmallVector optimization.
▶ Undocumented “UIO MAXIOV” limit in iovec.
▶ clean buffer on error
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tips
▶ Prefer “switch statements” to if-else condition.
▶ “Exception” and “heap allocation” are slow in C++.
▶ Avoid memory copy.
▶ SmallVector optimization.
▶ Undocumented “UIO MAXIOV” limit in iovec.
▶ clean buffer on error
▶ Server may refuse if too much data is “send”(sent) without
“recv”-ing
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tips
▶ Prefer “switch statements” to if-else condition.
▶ “Exception” and “heap allocation” are slow in C++.
▶ Avoid memory copy.
▶ SmallVector optimization.
▶ Undocumented “UIO MAXIOV” limit in iovec.
▶ clean buffer on error
▶ Server may refuse if too much data is “send”(sent) without
“recv”-ing
▶ Lazy connecting.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tips
▶ Prefer “switch statements” to if-else condition.
▶ “Exception” and “heap allocation” are slow in C++.
▶ Avoid memory copy.
▶ SmallVector optimization.
▶ Undocumented “UIO MAXIOV” limit in iovec.
▶ clean buffer on error
▶ Server may refuse if too much data is “send”(sent) without
“recv”-ing
▶ Lazy connecting.
▶ GIL issue.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tips
▶ Prefer “switch statements” to if-else condition.
▶ “Exception” and “heap allocation” are slow in C++.
▶ Avoid memory copy.
▶ SmallVector optimization.
▶ Undocumented “UIO MAXIOV” limit in iovec.
▶ clean buffer on error
▶ Server may refuse if too much data is “send”(sent) without
“recv”-ing
▶ Lazy connecting.
▶ GIL issue.
▶ gevent issue.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tips
▶ Prefer “switch statements” to if-else condition.
▶ “Exception” and “heap allocation” are slow in C++.
▶ Avoid memory copy.
▶ SmallVector optimization.
▶ Undocumented “UIO MAXIOV” limit in iovec.
▶ clean buffer on error
▶ Server may refuse if too much data is “send”(sent) without
“recv”-ing
▶ Lazy connecting.
▶ GIL issue.
▶ gevent issue.
▶ man 2 recv: For TCP sockets, the return value 0 means the
peer has closed its half side of the connection.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tips
▶ Prefer “switch statements” to if-else condition.
▶ “Exception” and “heap allocation” are slow in C++.
▶ Avoid memory copy.
▶ SmallVector optimization.
▶ Undocumented “UIO MAXIOV” limit in iovec.
▶ clean buffer on error
▶ Server may refuse if too much data is “send”(sent) without
“recv”-ing
▶ Lazy connecting.
▶ GIL issue.
▶ gevent issue.
▶ man 2 recv: For TCP sockets, the return value 0 means the
peer has closed its half side of the connection.
▶ write the right benchmark. bench order? dependency?
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tips
▶ Prefer “switch statements” to if-else condition.
▶ “Exception” and “heap allocation” are slow in C++.
▶ Avoid memory copy.
▶ SmallVector optimization.
▶ Undocumented “UIO MAXIOV” limit in iovec.
▶ clean buffer on error
▶ Server may refuse if too much data is “send”(sent) without
“recv”-ing
▶ Lazy connecting.
▶ GIL issue.
▶ gevent issue.
▶ man 2 recv: For TCP sockets, the return value 0 means the
peer has closed its half side of the connection.
▶ write the right benchmark. bench order? dependency?
▶ md5 is slow. bugfree fnv1 is hard to implement.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tips
▶ Prefer “switch statements” to if-else condition.
▶ “Exception” and “heap allocation” are slow in C++.
▶ Avoid memory copy.
▶ SmallVector optimization.
▶ Undocumented “UIO MAXIOV” limit in iovec.
▶ clean buffer on error
▶ Server may refuse if too much data is “send”(sent) without
“recv”-ing
▶ Lazy connecting.
▶ GIL issue.
▶ gevent issue.
▶ man 2 recv: For TCP sockets, the return value 0 means the
peer has closed its half side of the connection.
▶ write the right benchmark. bench order? dependency?
▶ md5 is slow. bugfree fnv1 is hard to implement.
▶ vim: Rip-Rip/clang complete + cpplint.py
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Outline
Wordplay
The memcached family
Why reinventing the new wheel
Bad things of libmemcached
Design a new memcached client
The ASCII protocol(get/set part)
Module Diagram
BufferWriter
BufferReader
Other parts
Lessons I learned
Tips
Great Toolchain
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Great Toolchain
▶ CMake
▶ Valgrind
▶ Callgrind(valgrind –tool=callgrind) +
kcachegrind/qcachegrind
▶ googletest
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Links I
libmc: https://github.com/douban/libmc
benchmark of libmc: https:
//gist.github.com/mckelvin/8ded053f6523931765d4
Improving performance of std::vector:
http://fahrenheit2539.blogspot.com/2012/06/
introduction-in-depths-look-at.html
How to profile C++ application with Callgrind / KCacheGrind:
http://baptiste-wicht.com/posts/2011/09/
profile-c-application-with-callgrind-kcachegrind.
html

Reinventing the wheel: libmc