Changeset 724
- Timestamp:
- 02/25/08 16:56:45 (6 months ago)
- Files:
-
- trunk/server/configure.ac (modified) (1 diff)
- trunk/server/doc/memory_management.txt (modified) (2 diffs)
- trunk/server/memcached.c (modified) (6 diffs)
- trunk/server/slabs.c (modified) (5 diffs)
- trunk/server/slabs.h (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/server/configure.ac
r703 r724 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) trunk/server/doc/memory_management.txt
r120 r724 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 trunk/server/memcached.c
r712 r724 2694 2694 "-P <file> save PID in <file>, only used with -d option\n" 2695 2695 "-f <factor> chunk size growth factor, default 1.25\n" 2696 "-n <bytes> minimum space allocated for key+value+flags, default 48\n"); 2696 "-n <bytes> minimum space allocated for key+value+flags, default 48\n" 2697 2698 #if defined(HAVE_GETPAGESIZES) && defined(HAVE_MEMCNTL) 2699 "-L Try to use large memory pages (if available). Increasing\n" 2700 " the memory page size could reduce the number of TLB misses\n" 2701 " and improve the performance. In order to get large pages\n" 2702 " from the OS, memcached will allocate the total item-cache\n" 2703 " in one large chunk.\n" 2704 #endif 2705 ); 2706 2697 2707 #ifdef USE_THREADS 2698 2708 printf("-t <num> number of threads to use, default 4\n"); … … 2805 2815 } 2806 2816 2817 #if defined(HAVE_GETPAGESIZES) && defined(HAVE_MEMCNTL) 2818 /* 2819 * On systems that supports multiple page sizes we may reduce the 2820 * number of TLB-misses by using the biggest available page size 2821 */ 2822 int enable_large_pages(void) { 2823 int ret = -1; 2824 size_t sizes[32]; 2825 int avail = getpagesizes(sizes, 32); 2826 if (avail != -1) { 2827 size_t max = sizes[0]; 2828 struct memcntl_mha arg = {0}; 2829 int ii; 2830 2831 for (ii = 1; ii < avail; ++ii) { 2832 if (max < sizes[ii]) { 2833 max = sizes[ii]; 2834 } 2835 } 2836 2837 arg.mha_flags = 0; 2838 arg.mha_pagesize = max; 2839 arg.mha_cmd = MHA_MAPSIZE_BSSBRK; 2840 2841 if (memcntl(0, 0, MC_HAT_ADVISE, (caddr_t)&arg, 0, 0) == -1) { 2842 fprintf(stderr, "Failed to set large pages: %s\n", 2843 strerror(errno)); 2844 fprintf(stderr, "Will use default page size\n"); 2845 } else { 2846 ret = 0; 2847 } 2848 } else { 2849 fprintf(stderr, "Failed to get supported pagesizes: %s\n", 2850 strerror(errno)); 2851 fprintf(stderr, "Will use default page size\n"); 2852 } 2853 2854 return ret; 2855 } 2856 #endif 2857 2807 2858 int main (int argc, char **argv) { 2808 2859 int c; … … 2810 2861 bool lock_memory = false; 2811 2862 bool daemonize = false; 2863 bool preallocate = false; 2812 2864 int maxcore = 0; 2813 2865 char *username = NULL; … … 2834 2886 2835 2887 /* process arguments */ 2836 while ((c = getopt(argc, argv, "a:bp:s:U:m:Mc:khirvdl:u:P:f:s:n:t:D: ")) != -1) {2888 while ((c = getopt(argc, argv, "a:bp:s:U:m:Mc:khirvdl:u:P:f:s:n:t:D:L")) != -1) { 2837 2889 switch (c) { 2838 2890 case 'a': … … 2918 2970 settings.detail_enabled = 1; 2919 2971 break; 2972 #if defined(HAVE_GETPAGESIZES) && defined(HAVE_MEMCNTL) 2973 case 'L' : 2974 if (enable_large_pages() == 0) { 2975 preallocate = true; 2976 } 2977 break; 2978 #endif 2920 2979 default: 2921 2980 fprintf(stderr, "Illegal argument \"%c\"\n", c); … … 3057 3116 /* Hacky suffix buffers. */ 3058 3117 suffix_init(); 3059 slabs_init(settings.maxbytes, settings.factor );3118 slabs_init(settings.maxbytes, settings.factor, preallocate); 3060 3119 3061 3120 /* managed instance? alloc and zero a bucket array */ trunk/server/slabs.c
r696 r724 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 } trunk/server/slabs.h
r596 r724 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
