1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/glib/tsrc/BC/tests/slice-test.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,297 @@
1.4 +/* GLIB sliced memory - fast threaded memory chunk allocator
1.5 + * Copyright (C) 2005 Tim Janik
1.6 + * Portion Copyright © 2008-09 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
1.7 + * This library is free software; you can redistribute it and/or
1.8 + * modify it under the terms of the GNU Lesser General Public
1.9 + * License as published by the Free Software Foundation; either
1.10 + * version 2 of the License, or (at your option) any later version.
1.11 + *
1.12 + * This library is distributed in the hope that it will be useful,
1.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1.15 + * Lesser General Public License for more details.
1.16 + *
1.17 + * You should have received a copy of the GNU Lesser General Public
1.18 + * License along with this library; if not, write to the
1.19 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1.20 + * Boston, MA 02111-1307, USA.
1.21 + */
1.22 +#include <glib.h>
1.23 +
1.24 +#include <stdio.h>
1.25 +#include <string.h>
1.26 +#include <sys/time.h> // gettimeofday
1.27 +#include <stdlib.h>
1.28 +
1.29 +#define quick_rand32() (rand_accu = 1664525 * rand_accu + 1013904223, rand_accu)
1.30 +static guint prime_size = 1021; // 769; // 509
1.31 +static gboolean clean_memchunks = FALSE;
1.32 +static guint number_of_blocks = 10000; /* total number of blocks allocated */
1.33 +static guint number_of_repetitions = 10000; /* number of alloc+free repetitions */
1.34 +
1.35 +/* --- old memchunk prototypes (memchunks.c) --- */
1.36 +void old_mem_chunks_init (void);
1.37 +GMemChunk* old_mem_chunk_new (const gchar *name,
1.38 + gint atom_size,
1.39 + gulong area_size,
1.40 + gint type);
1.41 +void old_mem_chunk_destroy (GMemChunk *mem_chunk);
1.42 +gpointer old_mem_chunk_alloc (GMemChunk *mem_chunk);
1.43 +gpointer old_mem_chunk_alloc0 (GMemChunk *mem_chunk);
1.44 +void old_mem_chunk_free (GMemChunk *mem_chunk,
1.45 + gpointer mem);
1.46 +void old_mem_chunk_clean (GMemChunk *mem_chunk);
1.47 +void old_mem_chunk_reset (GMemChunk *mem_chunk);
1.48 +void old_mem_chunk_print (GMemChunk *mem_chunk);
1.49 +void old_mem_chunk_info (void);
1.50 +#ifndef G_ALLOC_AND_FREE
1.51 +#define G_ALLOC_AND_FREE 2
1.52 +#endif
1.53 +
1.54 +/* --- functions --- */
1.55 +static inline gpointer
1.56 +memchunk_alloc (GMemChunk **memchunkp,
1.57 + guint size)
1.58 +{
1.59 + size = MAX (size, 1);
1.60 + if (G_UNLIKELY (!*memchunkp))
1.61 + *memchunkp = old_mem_chunk_new ("", size, 4096, G_ALLOC_AND_FREE);
1.62 + return old_mem_chunk_alloc (*memchunkp);
1.63 +}
1.64 +
1.65 +static inline void
1.66 +memchunk_free (GMemChunk *memchunk,
1.67 + gpointer chunk)
1.68 +{
1.69 + old_mem_chunk_free (memchunk, chunk);
1.70 + if (clean_memchunks)
1.71 + old_mem_chunk_clean (memchunk);
1.72 +}
1.73 +
1.74 +static gpointer
1.75 +test_memchunk_thread (gpointer data)
1.76 +{
1.77 + GMemChunk **memchunks;
1.78 + guint i, j;
1.79 + guint8 **ps;
1.80 + guint *ss;
1.81 + guint32 rand_accu = 2147483563;
1.82 + /* initialize random numbers */
1.83 + if (data)
1.84 + rand_accu = *(guint32*) data;
1.85 + else
1.86 + {
1.87 + struct timeval rand_tv;
1.88 + gettimeofday (&rand_tv, NULL);
1.89 + rand_accu = rand_tv.tv_usec + (rand_tv.tv_sec << 16);
1.90 + }
1.91 +
1.92 + /* prepare for memchunk creation */
1.93 + memchunks = g_alloca (sizeof (memchunks[0]) * prime_size);
1.94 + memset (memchunks, 0, sizeof (memchunks[0]) * prime_size);
1.95 +
1.96 + ps = g_new (guint8*, number_of_blocks);
1.97 + ss = g_new (guint, number_of_blocks);
1.98 + /* create number_of_blocks random sizes */
1.99 + for (i = 0; i < number_of_blocks; i++)
1.100 + ss[i] = quick_rand32() % prime_size;
1.101 + /* allocate number_of_blocks blocks */
1.102 + for (i = 0; i < number_of_blocks; i++)
1.103 + ps[i] = memchunk_alloc (&memchunks[ss[i]], ss[i]);
1.104 + for (j = 0; j < number_of_repetitions; j++)
1.105 + {
1.106 + /* free number_of_blocks/2 blocks */
1.107 + for (i = 0; i < number_of_blocks; i += 2)
1.108 + memchunk_free (memchunks[ss[i]], ps[i]);
1.109 + /* allocate number_of_blocks/2 blocks with new sizes */
1.110 + for (i = 0; i < number_of_blocks; i += 2)
1.111 + {
1.112 + ss[i] = quick_rand32() % prime_size;
1.113 + ps[i] = memchunk_alloc (&memchunks[ss[i]], ss[i]);
1.114 + }
1.115 + }
1.116 + /* free number_of_blocks blocks */
1.117 + for (i = 0; i < number_of_blocks; i++)
1.118 + memchunk_free (memchunks[ss[i]], ps[i]);
1.119 + /* alloc and free many equally sized chunks in a row */
1.120 + for (i = 0; i < number_of_repetitions; i++)
1.121 + {
1.122 + guint sz = quick_rand32() % prime_size;
1.123 + guint k = number_of_blocks / 100;
1.124 + for (j = 0; j < k; j++)
1.125 + ps[j] = memchunk_alloc (&memchunks[sz], sz);
1.126 + for (j = 0; j < k; j++)
1.127 + memchunk_free (memchunks[sz], ps[j]);
1.128 + }
1.129 + /* cleanout memchunks */
1.130 + for (i = 0; i < prime_size; i++)
1.131 + if (memchunks[i])
1.132 + old_mem_chunk_destroy (memchunks[i]);
1.133 + g_free (ps);
1.134 + g_free (ss);
1.135 +
1.136 + return NULL;
1.137 +}
1.138 +
1.139 +static gpointer
1.140 +test_sliced_mem_thread (gpointer data)
1.141 +{
1.142 +guint i, j;
1.143 +guint *ss;
1.144 +
1.145 +guint8 **ps;
1.146 + guint32 rand_accu = 2147483563;
1.147 + /* initialize random numbers */
1.148 + if (data)
1.149 + rand_accu = *(guint32*) data;
1.150 + else
1.151 + {
1.152 + struct timeval rand_tv;
1.153 + gettimeofday (&rand_tv, NULL);
1.154 + rand_accu = rand_tv.tv_usec + (rand_tv.tv_sec << 16);
1.155 + }
1.156 +
1.157 +//guint i,j;
1.158 +/* guint8*/ ps = g_new (guint8*, number_of_blocks);
1.159 +/* guint*/ ss = g_new (guint, number_of_blocks);
1.160 + /* create number_of_blocks random sizes */
1.161 + for (i = 0; i < number_of_blocks; i++)
1.162 + ss[i] = quick_rand32() % prime_size;
1.163 + /* allocate number_of_blocks blocks */
1.164 + for (i = 0; i < number_of_blocks; i++)
1.165 + ps[i] = g_slice_alloc (ss[i]);
1.166 + for (j = 0; j < number_of_repetitions; j++)
1.167 + {
1.168 + /* free number_of_blocks/2 blocks */
1.169 + for (i = 0; i < number_of_blocks; i += 2)
1.170 + g_slice_free1 (ss[i], ps[i]);
1.171 + /* allocate number_of_blocks/2 blocks with new sizes */
1.172 + for (i = 0; i < number_of_blocks; i += 2)
1.173 + {
1.174 + ss[i] = quick_rand32() % prime_size;
1.175 + ps[i] = g_slice_alloc (ss[i]);
1.176 + }
1.177 + }
1.178 + /* free number_of_blocks blocks */
1.179 + for (i = 0; i < number_of_blocks; i++)
1.180 + g_slice_free1 (ss[i], ps[i]);
1.181 + /* alloc and free many equally sized chunks in a row */
1.182 + for (i = 0; i < number_of_repetitions; i++)
1.183 + {
1.184 + guint sz = quick_rand32() % prime_size;
1.185 + guint k = number_of_blocks / 100;
1.186 + for (j = 0; j < k; j++)
1.187 + ps[j] = g_slice_alloc (sz);
1.188 + for (j = 0; j < k; j++)
1.189 + g_slice_free1 (sz, ps[j]);
1.190 + }
1.191 + g_free (ps);
1.192 + g_free (ss);
1.193 +
1.194 + return NULL;
1.195 +}
1.196 +
1.197 +static void
1.198 +usage (void)
1.199 +{
1.200 + g_print ("Usage: slice-test [n_threads] [G|S|M|O][f][c] [maxblocksize] [seed]\n");
1.201 +}
1.202 +
1.203 +int
1.204 +main (int argc,
1.205 + char *argv[])
1.206 +{
1.207 + gchar strseed[64] = "<random>";
1.208 +
1.209 + guint seed32, *seedp = NULL;
1.210 + gboolean ccounters = FALSE, use_memchunks = FALSE;
1.211 + guint n_threads = 1;
1.212 + guint i;
1.213 + GThread *threads[1];
1.214 + const gchar *mode = "slab allocator + magazine cache", *emode = " ";
1.215 + if (argc > 1)
1.216 + n_threads = g_ascii_strtoull (argv[1], NULL, 10);
1.217 + if (argc > 2)
1.218 + {
1.219 + guint i, l = strlen (argv[2]);
1.220 + for (i = 0; i < l; i++)
1.221 + switch (argv[2][i])
1.222 + {
1.223 + case 'G': /* GLib mode */
1.224 + g_slice_set_config (G_SLICE_CONFIG_ALWAYS_MALLOC, FALSE);
1.225 + g_slice_set_config (G_SLICE_CONFIG_BYPASS_MAGAZINES, FALSE);
1.226 + mode = "slab allocator + magazine cache";
1.227 + break;
1.228 + case 'S': /* slab mode */
1.229 + g_slice_set_config (G_SLICE_CONFIG_ALWAYS_MALLOC, FALSE);
1.230 + g_slice_set_config (G_SLICE_CONFIG_BYPASS_MAGAZINES, TRUE);
1.231 + mode = "slab allocator";
1.232 + break;
1.233 + case 'M': /* malloc mode */
1.234 + g_slice_set_config (G_SLICE_CONFIG_ALWAYS_MALLOC, TRUE);
1.235 + mode = "system malloc";
1.236 + break;
1.237 + case 'O': /* old memchunks */
1.238 + use_memchunks = TRUE;
1.239 + mode = "old memchunks";
1.240 + break;
1.241 + case 'f': /* eager freeing */
1.242 + g_slice_set_config (G_SLICE_CONFIG_WORKING_SET_MSECS, 0);
1.243 + clean_memchunks = TRUE;
1.244 + emode = " with eager freeing";
1.245 + break;
1.246 + case 'c': /* print contention counters */
1.247 + ccounters = TRUE;
1.248 + break;
1.249 + default:
1.250 + usage();
1.251 + return 1;
1.252 + }
1.253 + }
1.254 + if (argc > 3)
1.255 + prime_size = g_ascii_strtoull (argv[3], NULL, 10);
1.256 + if (argc > 4)
1.257 + {
1.258 + seed32 = g_ascii_strtoull (argv[4], NULL, 10);
1.259 + seedp = &seed32;
1.260 + }
1.261 +
1.262 + g_thread_init (NULL);
1.263 +
1.264 + if (argc <= 1)
1.265 + usage();
1.266 +
1.267 + // gchar strseed[64] = "<random>";
1.268 + if (seedp)
1.269 + g_snprintf (strseed, 64, "%u", *seedp);
1.270 + g_print ("Starting %d threads allocating random blocks <= %u bytes with seed=%s using %s%s\n", n_threads, prime_size, strseed, mode, emode);
1.271 +
1.272 +// GThread *threads[n_threads];
1.273 +// guint i;
1.274 + if (!use_memchunks)
1.275 + for (i = 0; i < n_threads; i++)
1.276 + threads[i] = g_thread_create_full (test_sliced_mem_thread, seedp, 0, TRUE, FALSE, 0, NULL);
1.277 + else
1.278 + {
1.279 + old_mem_chunks_init();
1.280 + for (i = 0; i < n_threads; i++)
1.281 + threads[i] = g_thread_create_full (test_memchunk_thread, seedp, 0, TRUE, FALSE, 0, NULL);
1.282 + }
1.283 + for (i = 0; i < n_threads; i++)
1.284 + g_thread_join (threads[i]);
1.285 +
1.286 + if (ccounters)
1.287 + {
1.288 + guint n, n_chunks = g_slice_get_config (G_SLICE_CONFIG_CHUNK_SIZES);
1.289 + g_print (" ChunkSize | MagazineSize | Contention\n");
1.290 + for (i = 0; i < n_chunks; i++)
1.291 + {
1.292 + gint64 *vals = g_slice_get_config_state (G_SLICE_CONFIG_CONTENTION_COUNTER, i, &n);
1.293 + g_print (" %9llu | %9llu | %9llu\n", vals[0], vals[2], vals[1]);
1.294 + g_free (vals);
1.295 + }
1.296 + }
1.297 + else
1.298 + g_print ("Done.\n");
1.299 + return 0;
1.300 +}