Changeset 725

Show
Ignore:
Timestamp:
02/25/08 18:37:08 (6 months ago)
Author:
dsallings
Message:

Merge commit 'trunk' into lbinary as of r724

Conflicts:

server/memcached.c

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/binary/server/configure.ac

    r717 r725  
    200200 
    201201AC_CHECK_FUNCS(mlockall) 
     202AC_CHECK_FUNCS(getpagesizes) 
     203AC_CHECK_FUNCS(memcntl) 
    202204 
    203205AC_CONFIG_FILES(Makefile doc/Makefile) 
  • branches/binary/server/doc/memory_management.txt

    r120 r725  
     1Date: Tue, 20 Feb 2008 
     2From: Trond Norbye <trond.norbye@sun.com> 
     3 
     4When started with -L memcached will try to enable large memory 
     5pages, and preallocate all memory up front. By using large memory 
     6pages memcached could reduce the number of TLB misses (depending 
     7on the access pattern), and hence improve performance.  
     8 
     9See http://en.wikipedia.org/wiki/Translation_lookaside_buffer for 
     10a description of TLB. 
     11 
    112Date: Fri, 5 Sep 2003 20:31:03 +0300 
    213From: Anatoly Vorobey <mellon@pobox.com> 
     
    4556that's at all possible) common sizes of objects that the clients 
    4657of this particular installation of memcached are likely to store. 
    47 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 
     58For example, if your installation is going to store hundreds of 
     59thousands of objects of the size exactly 120 bytes, you'd be much better 
    4860off changing, in the "naive" list of sizes outlined above, the class 
    4961of 128 bytes to something a bit higher (because the overhead of  
  • branches/binary/server/memcached.c

    r722 r725  
    32903290           "-P <file>     save PID in <file>, only used with -d option\n" 
    32913291           "-f <factor>   chunk size growth factor, default 1.25\n" 
    3292            "-n <bytes>    minimum space allocated for key+value+flags, default 48\n"); 
     3292           "-n <bytes>    minimum space allocated for key+value+flags, default 48\n" 
     3293 
     3294#if defined(HAVE_GETPAGESIZES) && defined(HAVE_MEMCNTL) 
     3295           "-L            Try to use large memory pages (if available). Increasing\n" 
     3296           "              the memory page size could reduce the number of TLB misses\n" 
     3297           "              and improve the performance. In order to get large pages\n" 
     3298           "              from the OS, memcached will allocate the total item-cache\n" 
     3299           "              in one large chunk.\n" 
     3300#endif 
     3301           ); 
     3302 
    32933303#ifdef USE_THREADS 
    32943304    printf("-t <num>      number of threads to use, default 4\n"); 
     
    34243434} 
    34253435 
     3436#if defined(HAVE_GETPAGESIZES) && defined(HAVE_MEMCNTL) 
     3437/* 
     3438 * On systems that supports multiple page sizes we may reduce the 
     3439 * number of TLB-misses by using the biggest available page size 
     3440 */ 
     3441int enable_large_pages(void) { 
     3442    int ret = -1; 
     3443    size_t sizes[32]; 
     3444    int avail = getpagesizes(sizes, 32); 
     3445    if (avail != -1) { 
     3446        size_t max = sizes[0]; 
     3447        struct memcntl_mha arg = {0}; 
     3448        int ii; 
     3449 
     3450        for (ii = 1; ii < avail; ++ii) { 
     3451            if (max < sizes[ii]) { 
     3452                max = sizes[ii]; 
     3453            } 
     3454        } 
     3455 
     3456        arg.mha_flags   = 0; 
     3457        arg.mha_pagesize = max; 
     3458        arg.mha_cmd = MHA_MAPSIZE_BSSBRK; 
     3459 
     3460        if (memcntl(0, 0, MC_HAT_ADVISE, (caddr_t)&arg, 0, 0) == -1) { 
     3461            fprintf(stderr, "Failed to set large pages: %s\n", 
     3462                    strerror(errno)); 
     3463            fprintf(stderr, "Will use default page size\n"); 
     3464        } else { 
     3465            ret = 0; 
     3466        } 
     3467    } else { 
     3468        fprintf(stderr, "Failed to get supported pagesizes: %s\n", 
     3469                strerror(errno)); 
     3470        fprintf(stderr, "Will use default page size\n"); 
     3471    } 
     3472 
     3473    return ret; 
     3474} 
     3475#endif 
     3476 
    34263477int main (int argc, char **argv) { 
    34273478    int c; 
    34283479    bool lock_memory = false; 
    34293480    bool daemonize = false; 
     3481    bool preallocate = false; 
    34303482    int maxcore = 0; 
    34313483    char *username = NULL; 
     
    35413593            settings.detail_enabled = 1; 
    35423594            break; 
     3595#if defined(HAVE_GETPAGESIZES) && defined(HAVE_MEMCNTL) 
     3596        case 'L' : 
     3597            if (enable_large_pages() == 0) { 
     3598                preallocate = true; 
     3599            } 
     3600            break; 
     3601#endif 
    35433602        default: 
    35443603            fprintf(stderr, "Illegal argument \"%c\"\n", c); 
     
    36893748    /* Hacky suffix buffers. */ 
    36903749    suffix_init(); 
    3691     slabs_init(settings.maxbytes, settings.factor); 
     3750    slabs_init(settings.maxbytes, settings.factor, preallocate); 
    36923751 
    36933752    /* managed instance? alloc and zero a bucket array */ 
  • branches/binary/server/slabs.c

    r717 r725  
    5555static int power_largest; 
    5656 
     57static void *mem_base = NULL; 
     58static void *mem_current = NULL; 
     59static size_t mem_avail = 0; 
     60 
    5761/* 
    5862 * Forward Declarations 
    5963 */ 
    6064static int do_slabs_newslab(const unsigned int id); 
     65static void *memory_allocate(size_t size); 
    6166 
    6267#ifndef DONT_PREALLOC_SLABS 
     
    9398 * accordingly. 
    9499 */ 
    95 void slabs_init(const size_t limit, const double factor) { 
     100void slabs_init(const size_t limit, const double factor, const bool prealloc) { 
    96101    int i = POWER_SMALLEST - 1; 
    97102    unsigned int size = sizeof(item) + settings.chunk_size; 
     
    102107 
    103108    mem_limit = limit; 
     109 
     110    if (prealloc) { 
     111        /* Allocate everything in a big chunk with malloc */ 
     112        mem_base = malloc(mem_limit); 
     113        if (mem_base != NULL) { 
     114            mem_current = mem_base; 
     115            mem_avail = mem_limit; 
     116        } else { 
     117            fprintf(stderr, "Warning: Failed to allocate requested memory in" 
     118                    " one large chunk.\nWill allocate in smaller chunks\n"); 
     119        } 
     120    } 
     121 
    104122    memset(slabclass, 0, sizeof(slabclass)); 
    105123 
     
    188206    if (grow_slab_list(id) == 0) return 0; 
    189207 
    190     ptr = malloc((size_t)len); 
     208    ptr = memory_allocate((size_t)len); 
    191209    if (ptr == 0) return 0; 
    192210 
     
    375393} 
    376394#endif 
     395 
     396static void *memory_allocate(size_t size) { 
     397    void *ret; 
     398 
     399    if (mem_base == NULL) { 
     400        /* We are not using a preallocated large memory chunk */ 
     401        ret = malloc(size); 
     402    } else { 
     403        ret = mem_current; 
     404 
     405        if (size > mem_avail) { 
     406            return NULL; 
     407        } 
     408 
     409        /* mem_current pointer _must_ be aligned!!! */ 
     410        if (size % CHUNK_ALIGN_BYTES) { 
     411            size += CHUNK_ALIGN_BYTES - (size % CHUNK_ALIGN_BYTES); 
     412        } 
     413 
     414        mem_current += size; 
     415        if (size < mem_avail) { 
     416            mem_avail -= size; 
     417        } else { 
     418            mem_avail = 0; 
     419        } 
     420    } 
     421 
     422    return ret; 
     423} 
  • branches/binary/server/slabs.h

    r596 r725  
    33/** Init the subsystem. 1st argument is the limit on no. of bytes to allocate, 
    44    0 if no limit. 2nd argument is the growth factor; each slab will use a chunk 
    5     size equal to the previous slab's chunk size times this factor. */ 
    6 void slabs_init(const size_t limit, const double factor); 
     5    size equal to the previous slab's chunk size times this factor. 
     6    3rd argument specifies if the slab allocator should allocate all memory 
     7    up front (if true), or allocate memory in chunks as it is needed (if false) 
     8*/ 
     9void slabs_init(const size_t limit, const double factor, const bool prealloc); 
    710 
    811