• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.1 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, see <http://www.gnu.org/licenses/>.
16  */
17 #include <glib.h>
18 #include <string.h>
19 
20 #define ALIGN(size, base)       ((base) * (gsize) (((size) + (base) - 1) / (base)))
21 
22 static gdouble parse_memsize (const gchar *cstring);
23 static void    usage         (void);
24 
25 static void
fill_memory(guint ** mem,guint n,guint val)26 fill_memory (guint **mem,
27              guint   n,
28              guint   val)
29 {
30   guint j, o = 0;
31   for (j = 0; j < n; j++)
32     mem[j][o] = val;
33 }
34 
35 static guint64
access_memory3(guint ** mema,guint ** memb,guint ** memd,guint n,guint64 repeats)36 access_memory3 (guint  **mema,
37                 guint  **memb,
38                 guint  **memd,
39                 guint    n,
40                 guint64  repeats)
41 {
42   guint64 accu = 0, i, j;
43   const guint o = 0;
44   for (i = 0; i < repeats; i++)
45     {
46       for (j = 1; j < n; j += 2)
47         memd[j][o] = mema[j][o] + memb[j][o];
48     }
49   for (i = 0; i < repeats; i++)
50     for (j = 0; j < n; j++)
51       accu += memd[j][o];
52   return accu;
53 }
54 
55 static void
touch_mem(guint64 block_size,guint64 n_blocks,guint64 repeats)56 touch_mem (guint64 block_size,
57            guint64 n_blocks,
58            guint64 repeats)
59 {
60   guint64 j, accu, n = n_blocks;
61   GTimer *timer;
62   guint **memc;
63   guint **memb;
64   guint **mema = g_new (guint*, n);
65   for (j = 0; j < n; j++)
66     mema[j] = g_slice_alloc (block_size);
67   memb = g_new (guint*, n);
68   for (j = 0; j < n; j++)
69     memb[j] = g_slice_alloc (block_size);
70   memc = g_new (guint*, n);
71   for (j = 0; j < n; j++)
72     memc[j] = g_slice_alloc (block_size);
73 
74   timer = g_timer_new();
75   fill_memory (mema, n, 2);
76   fill_memory (memb, n, 3);
77   fill_memory (memc, n, 4);
78   access_memory3 (mema, memb, memc, n, 3);
79   g_timer_start (timer);
80   accu = access_memory3 (mema, memb, memc, n, repeats);
81   g_timer_stop (timer);
82 
83   g_print ("Access-time = %fs\n", g_timer_elapsed (timer, NULL));
84   g_assert (accu / repeats == (2 + 3) * n / 2 + 4 * n / 2);
85 
86   for (j = 0; j < n; j++)
87     {
88       g_slice_free1 (block_size, mema[j]);
89       g_slice_free1 (block_size, memb[j]);
90       g_slice_free1 (block_size, memc[j]);
91     }
92   g_timer_destroy (timer);
93   g_free (mema);
94   g_free (memb);
95   g_free (memc);
96 }
97 
98 static void
usage(void)99 usage (void)
100 {
101   g_print ("Usage: slice-color <block-size> [memory-size] [repeats] [colorization]\n");
102 }
103 
104 int
main(int argc,char * argv[])105 main (int   argc,
106       char *argv[])
107 {
108   guint64 block_size = 512, area_size = 1024 * 1024, n_blocks, repeats = 1000000;
109 
110   if (argc > 1)
111     block_size = parse_memsize (argv[1]);
112   else
113     {
114       usage();
115       block_size = 512;
116     }
117   if (argc > 2)
118     area_size = parse_memsize (argv[2]);
119   if (argc > 3)
120     repeats = parse_memsize (argv[3]);
121   if (argc > 4)
122     g_slice_set_config (G_SLICE_CONFIG_COLOR_INCREMENT, parse_memsize (argv[4]));
123 
124   /* figure number of blocks from block and area size.
125    * divide area by 3 because touch_mem() allocates 3 areas
126    */
127   n_blocks = area_size / 3 / ALIGN (block_size, sizeof (gsize) * 2);
128 
129   /* basic sanity checks */
130   if (!block_size || !n_blocks || block_size >= area_size)
131     {
132       g_printerr ("Invalid arguments: block-size=%" G_GUINT64_FORMAT " memory-size=%" G_GUINT64_FORMAT "\n", block_size, area_size);
133       usage();
134       return 1;
135     }
136 
137   g_printerr ("Will allocate and touch %" G_GUINT64_FORMAT " blocks of %" G_GUINT64_FORMAT " bytes (= %" G_GUINT64_FORMAT " bytes) %" G_GUINT64_FORMAT " times with color increment: 0x%08" G_GINT64_MODIFIER "x\n",
138               n_blocks, block_size, n_blocks * block_size, repeats,
139 	      (guint64)g_slice_get_config (G_SLICE_CONFIG_COLOR_INCREMENT));
140 
141   touch_mem (block_size, n_blocks, repeats);
142 
143   return 0;
144 }
145 
146 static gdouble
parse_memsize(const gchar * cstring)147 parse_memsize (const gchar *cstring)
148 {
149   gchar *mem = g_strdup (cstring);
150   gchar *string = g_strstrip (mem);
151   guint l = strlen (string);
152   gdouble f = 0;
153   gchar *derr = NULL;
154   gdouble msize;
155 
156   switch (l ? string[l - 1] : 0)
157     {
158     case 'k':   f = 1000;               break;
159     case 'K':   f = 1024;               break;
160     case 'm':   f = 1000000;            break;
161     case 'M':   f = 1024 * 1024;        break;
162     case 'g':   f = 1000000000;         break;
163     case 'G':   f = 1024 * 1024 * 1024; break;
164     }
165   if (f)
166     string[l - 1] = 0;
167   msize = g_ascii_strtod (string, &derr);
168   g_free (mem);
169   if (derr && *derr)
170     {
171       g_printerr ("failed to parse number at: %s\n", derr);
172       msize = 0;
173     }
174   if (f)
175     msize *= f;
176   return msize;
177 }
178