Mercurial > hg > memcached
diff doc/memory_management.txt @ 0:30782bb1fc04 MEMCACHED_1_2_3
memcached-1.2.3
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sun, 23 Sep 2007 03:58:34 +0400 |
parents | |
children |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/doc/memory_management.txt @@ -0,0 +1,83 @@ +Date: Fri, 5 Sep 2003 20:31:03 +0300 +From: Anatoly Vorobey <mellon@pobox.com> +To: memcached@lists.danga.com +Subject: Re: Memory Management... + +On Fri, Sep 05, 2003 at 12:07:48PM -0400, Kyle R. Burton wrote: +> prefixing keys with a container identifier). We have just begun to +> look at the implementation of the memory management sub-system with +> regards to it's allocation, de-allocation and compaction approaches. +> Is there any documentation or discussion of how this subsystem +> operates? (slabs.c?) + +There's no documentation yet, and it's worth mentioning that this +subsystem is the most active area of memcached under development at the +moment (however, all the changes to it won't modify the way memcached +presents itself towards clients, they're primarily directed at making +memcached use memory more efficiently). + +Here's a quick recap of what it does now and what is being worked +on. + +The primary goal of the slabs subsystem in memcached was to eliminate +memory fragmentation issues totally by using fixed-size memory chunks +coming from a few predetermined size classes (early versions of +memcached relied on malloc()'s handling of fragmentation which proved +woefully inadequate for our purposes). For instance, suppose +we decide at the outset that the list of possible sizes is: 64 bytes, +128 bytes, 256 bytes, etc. - doubling all the way up to 1Mb. For each +size class in this list (each possible size) we maintain a list of free +chunks of this size. Whenever a request comes for a particular size, +it is rounded up to the closest size class and a free chunk is taken +from that size class. In the above example, if you request from the +slabs subsystem 100 bytes of memory, you'll actually get a chunk 128 +bytes worth, from the 128-bytes size class. If there are no free chunks +of the needed size at the moment, there are two ways to get one: 1) free +an existing chunk in the same size class, using LRU queues to free the +least needed objects; 2) get more memory from the system, which we +currently always do in _slabs_ of 1Mb each; we malloc() a slab, divide +it to chunks of the needed size, and use them. + +The tradeoff is between memory fragmentation and memory utilisation. In +the scheme we're now using, we have zero fragmentation, but a relatively +high percentage of memory is wasted. The most efficient way to reduce +the waste is to use a list of size classes that closely matches (if +that's at all possible) common sizes of objects that the clients +of this particular installation of memcached are likely to store. +For example, if your installation is going to store hundreds of thousands of objects of the size exactly 120 bytes, you'd be much better +off changing, in the "naive" list of sizes outlined above, the class +of 128 bytes to something a bit higher (because the overhead of +storing an item, while not large, will push those 120-bytes objects over +128 bytes of storage internally, and will require using 256 bytes for +each of them in the naive scheme, forcing you to waste almost 50% of +memory). Such tinkering with the list of size classes is not currently +possible with memcached, but enabling it is one of the immediate goals. + +Ideally, the slabs subsystem would analyze at runtime the common sizes +of objects that are being requested, and would be able to modify the +list of sizes dynamically to improve memory utilisation. This is not +planned for the immediate future, however. What is planned is the +ability to reassign slabs to different classes. Here's what this means. +Currently, the total amount of memory allocated for each size class is +determined by how clients interact with memcached during the initial +phase of its execution, when it keeps malloc()'ing more slabs and +dividing them into chunks, until it hits the specified memory limit +(say, 2Gb, or whatever else was specified). Once it hits the limit, to +allocate a new chunk it'll always delete an existing chunk of the same +size (using LRU queues), and will never malloc() or free() any memory +from/to the system. So if, for example, during those initial few hours +of memcached's execution your clients mainly wanted to store very small +items, the bulk of memory allocated will be divided to small-sized +chunks, and the large size classes will get fewer memory, therefore the +life-cycle of large objects you'll store in memcached will henceforth +always be much shorter, with this instance of memcached (their LRU +queues will be shorter and they'll be pushed out much more often). In +general, if your system starts producing a different pattern of common +object sizes, the memcached servers will become less efficient, unless +you restart them. Slabs reassignment, which is the next feature being +worked on, will ensure the server's ability to reclaim a slab (1Mb of +memory) from one size class and put it into another class size, where +it's needed more. + +-- +avva