Home | History | Annotate | Download | only in tests
      1 /* GLIB sliced memory - fast threaded memory chunk allocator
      2  * Copyright (C) 2005 Tim Janik
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Lesser General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Lesser General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Lesser General Public
     15  * License along with this library; if not, write to the
     16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
     17  * Boston, MA 02111-1307, USA.
     18  */
     19 #include <glib.h>
     20 #include <string.h>
     21 
     22 #define ALIGN(size, base)       ((base) * (gsize) (((size) + (base) - 1) / (base)))
     23 
     24 static gdouble parse_memsize (const gchar *cstring);
     25 static void    usage         (void);
     26 
     27 static void
     28 fill_memory (guint **mem,
     29              guint   n,
     30              guint   val)
     31 {
     32   guint j, o = 0;
     33   for (j = 0; j < n; j++)
     34     mem[j][o] = val;
     35 }
     36 
     37 static guint64
     38 access_memory3 (guint  **mema,
     39                 guint  **memb,
     40                 guint  **memd,
     41                 guint    n,
     42                 guint64  repeats)
     43 {
     44   guint64 accu = 0, i, j;
     45   const guint o = 0;
     46   for (i = 0; i < repeats; i++)
     47     {
     48       for (j = 1; j < n; j += 2)
     49         memd[j][o] = mema[j][o] + memb[j][o];
     50     }
     51   for (i = 0; i < repeats; i++)
     52     for (j = 0; j < n; j++)
     53       accu += memd[j][o];
     54   return accu;
     55 }
     56 
     57 static void
     58 touch_mem (guint64 block_size,
     59            guint64 n_blocks,
     60            guint64 repeats)
     61 {
     62   guint64 j, accu, n = n_blocks;
     63   GTimer *timer;
     64   guint **memc;
     65   guint **memb;
     66   guint **mema = g_new (guint*, n);
     67   for (j = 0; j < n; j++)
     68     mema[j] = g_slice_alloc (block_size);
     69   memb = g_new (guint*, n);
     70   for (j = 0; j < n; j++)
     71     memb[j] = g_slice_alloc (block_size);
     72   memc = g_new (guint*, n);
     73   for (j = 0; j < n; j++)
     74     memc[j] = g_slice_alloc (block_size);
     75 
     76   timer = g_timer_new();
     77   fill_memory (mema, n, 2);
     78   fill_memory (memb, n, 3);
     79   fill_memory (memc, n, 4);
     80   access_memory3 (mema, memb, memc, n, 3);
     81   g_timer_start (timer);
     82   accu = access_memory3 (mema, memb, memc, n, repeats);
     83   g_timer_stop (timer);
     84 
     85   g_print ("Access-time = %fs\n", g_timer_elapsed (timer, NULL));
     86   g_assert (accu / repeats == (2 + 3) * n / 2 + 4 * n / 2);
     87 
     88   for (j = 0; j < n; j++)
     89     {
     90       g_slice_free1 (block_size, mema[j]);
     91       g_slice_free1 (block_size, memb[j]);
     92       g_slice_free1 (block_size, memc[j]);
     93     }
     94   g_timer_destroy (timer);
     95   g_free (mema);
     96   g_free (memb);
     97   g_free (memc);
     98 }
     99 
    100 static void
    101 usage (void)
    102 {
    103   g_print ("Usage: slice-color <block-size> [memory-size] [repeats] [colorization]\n");
    104 }
    105 
    106 int
    107 main (int   argc,
    108       char *argv[])
    109 {
    110   guint64 block_size = 512, area_size = 1024 * 1024, n_blocks, repeats = 1000000;
    111 
    112   if (argc > 1)
    113     block_size = parse_memsize (argv[1]);
    114   else
    115     {
    116       usage();
    117       block_size = 512;
    118     }
    119   if (argc > 2)
    120     area_size = parse_memsize (argv[2]);
    121   if (argc > 3)
    122     repeats = parse_memsize (argv[3]);
    123   if (argc > 4)
    124     g_slice_set_config (G_SLICE_CONFIG_COLOR_INCREMENT, parse_memsize (argv[4]));
    125 
    126   /* figure number of blocks from block and area size.
    127    * divide area by 3 because touch_mem() allocates 3 areas
    128    */
    129   n_blocks = area_size / 3 / ALIGN (block_size, sizeof (gsize) * 2);
    130 
    131   /* basic sanity checks */
    132   if (!block_size || !n_blocks || block_size >= area_size)
    133     {
    134       g_printerr ("Invalid arguments: block-size=%llu memory-size=%llu\n", block_size, area_size);
    135       usage();
    136       return 1;
    137     }
    138 
    139   g_printerr ("Will allocate and touch %llu blocks of %llu bytes (= %llu bytes) %llu times with color increment: 0x%08llx\n",
    140               n_blocks, block_size, n_blocks * block_size, repeats, g_slice_get_config (G_SLICE_CONFIG_COLOR_INCREMENT));
    141 
    142   touch_mem (block_size, n_blocks, repeats);
    143 
    144   return 0;
    145 }
    146 
    147 static gdouble
    148 parse_memsize (const gchar *cstring)
    149 {
    150   gchar *mem = g_strdup (cstring);
    151   gchar *string = g_strstrip (mem);
    152   guint l = strlen (string);
    153   gdouble f = 0;
    154   gchar *derr = NULL;
    155   gdouble msize;
    156 
    157   switch (l ? string[l - 1] : 0)
    158     {
    159     case 'k':   f = 1000;               break;
    160     case 'K':   f = 1024;               break;
    161     case 'm':   f = 1000000;            break;
    162     case 'M':   f = 1024 * 1024;        break;
    163     case 'g':   f = 1000000000;         break;
    164     case 'G':   f = 1024 * 1024 * 1024; break;
    165     }
    166   if (f)
    167     string[l - 1] = 0;
    168   msize = g_ascii_strtod (string, &derr);
    169   g_free (mem);
    170   if (derr && *derr)
    171     {
    172       g_printerr ("failed to parse number at: %s\n", derr);
    173       msize = 0;
    174     }
    175   if (f)
    176     msize *= f;
    177   return msize;
    178 }
    179