Changeset 725
- Timestamp:
- 02/25/08 18:37:08 (6 months ago)
- Files:
-
- branches/binary/server/configure.ac (modified) (1 diff)
- branches/binary/server/doc/memory_management.txt (modified) (2 diffs)
- branches/binary/server/memcached.c (modified) (4 diffs)
- branches/binary/server/slabs.c (modified) (5 diffs)
- branches/binary/server/slabs.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
branches/binary/server/configure.ac
r717 r725 200 200 201 201 AC_CHECK_FUNCS(mlockall) 202 AC_CHECK_FUNCS(getpagesizes) 203 AC_CHECK_FUNCS(memcntl) 202 204 203 205 AC_CONFIG_FILES(Makefile doc/Makefile) branches/binary/server/doc/memory_management.txt
r120 r725 1 Date: Tue, 20 Feb 2008 2 From: Trond Norbye <trond.norbye@sun.com> 3 4 When started with -L memcached will try to enable large memory 5 pages, and preallocate all memory up front. By using large memory 6 pages memcached could reduce the number of TLB misses (depending 7 on the access pattern), and hence improve performance. 8 9 See http://en.wikipedia.org/wiki/Translation_lookaside_buffer for 10 a description of TLB. 11 1 12 Date: Fri, 5 Sep 2003 20:31:03 +0300 2 13 From: Anatoly Vorobey <mellon@pobox.com> … … 45 56 that's at all possible) common sizes of objects that the clients 46 57 of 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 58 For example, if your installation is going to store hundreds of 59 thousands of objects of the size exactly 120 bytes, you'd be much better 48 60 off changing, in the "naive" list of sizes outlined above, the class 49 61 of 128 bytes to something a bit higher (because the overhead of branches/binary/server/memcached.c
r722 r725 3290 3290 "-P <file> save PID in <file>, only used with -d option\n" 3291 3291 "-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 3293 3303 #ifdef USE_THREADS 3294 3304 printf("-t <num> number of threads to use, default 4\n"); … … 3424 3434 } 3425 3435 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 */ 3441 int 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 3426 3477 int main (int argc, char **argv) { 3427 3478 int c; 3428 3479 bool lock_memory = false; 3429 3480 bool daemonize = false; 3481 bool preallocate = false; 3430 3482 int maxcore = 0; 3431 3483 char *username = NULL; … … 3541 3593 settings.detail_enabled = 1; 3542 3594 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 3543 3602 default: 3544 3603 fprintf(stderr, "Illegal argument \"%c\"\n", c); … … 3689 3748 /* Hacky suffix buffers. */ 3690 3749 suffix_init(); 3691 slabs_init(settings.maxbytes, settings.factor );3750 slabs_init(settings.maxbytes, settings.factor, preallocate); 3692 3751 3693 3752 /* managed instance? alloc and zero a bucket array */ branches/binary/server/slabs.c
r717 r725 55 55 static int power_largest; 56 56 57 static void *mem_base = NULL; 58 static void *mem_current = NULL; 59 static size_t mem_avail = 0; 60 57 61 /* 58 62 * Forward Declarations 59 63 */ 60 64 static int do_slabs_newslab(const unsigned int id); 65 static void *memory_allocate(size_t size); 61 66 62 67 #ifndef DONT_PREALLOC_SLABS … … 93 98 * accordingly. 94 99 */ 95 void slabs_init(const size_t limit, const double factor ) {100 void slabs_init(const size_t limit, const double factor, const bool prealloc) { 96 101 int i = POWER_SMALLEST - 1; 97 102 unsigned int size = sizeof(item) + settings.chunk_size; … … 102 107 103 108 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 104 122 memset(slabclass, 0, sizeof(slabclass)); 105 123 … … 188 206 if (grow_slab_list(id) == 0) return 0; 189 207 190 ptr = m alloc((size_t)len);208 ptr = memory_allocate((size_t)len); 191 209 if (ptr == 0) return 0; 192 210 … … 375 393 } 376 394 #endif 395 396 static 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 3 3 /** Init the subsystem. 1st argument is the limit on no. of bytes to allocate, 4 4 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 */ 9 void slabs_init(const size_t limit, const double factor, const bool prealloc); 7 10 8 11
