os/ossrv/glib/tsrc/BC/tests/slice-test.c
changeset 0 bde4ae8d615e
     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 +}