1 /* This file tests how efficient differrent lengths of _BUF nodes are and also
2  * compares them to one big pile
3  * -- vstr is kind of built on the idea that this isn't a problem for
4  *    reasonable sizes */
5 
6 #define VSTR_COMPILE_INCLUDE 1
7 
8 #include <vstr.h>
9 
10 #ifndef TST_SZ /* chunk size for custom Vstr */
11 # define TST_SZ (4096 - (sizeof(Vstr_node) + 8)) /* one page each */
12 #endif
13 
14 #ifndef TST_NUM /* number of times to perform each test */
15 # define TST_NUM (1024 * 128)
16 #endif
17 
18 #ifndef TST_LEN /* length of data for each test */
19 # define TST_LEN (512)
20 #endif
21 
22 #ifndef TST_MALLOC_EXTRA /* malloc extra bytes before each loop */
23 # define TST_MALLOC_EXTRA (0)
24 #endif
25 
26 #ifndef TST_FREE /* free the data from previous runs between each test */
27 # define TST_FREE (1)
28 #endif
29 
30 #ifndef TST_REUSE
31 # define TST_REUSE (0)
32 #endif
33 
34 #include "ex_perf.h"
35 
36 #include <assert.h>
37 
main(void)38 int main(void)
39 {
40   Vstr_conf *conf = NULL;
41   Vstr_base *out = NULL;
42   Vstr_base *s1 = NULL;
43   char *s2 = NULL;
44   Vstr_base *s3 = NULL;
45   unsigned int err = 0;
46   char *mal_overhead[TST_NUM];
47 
48   if (!vstr_init())
49     exit(EXIT_FAILURE);
50 
51   conf = vstr_make_conf();
52   if (!conf)
53     exit(EXIT_FAILURE);
54 
55   /* have a custom config. for output and s1 ... */
56   vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_NUM_BUF_SZ, TST_SZ);
57 
58   vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_LOC_CSTR_THOU_SEP, "_");
59   vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_LOC_CSTR_THOU_GRP, "\3");
60 
61   vstr_cntl_conf(conf, VSTR_CNTL_CONF_SET_FMT_CHAR_ESC, '$');
62   vstr_sc_fmt_add_all(conf);
63 
64   out = vstr_make_base(conf); /* used as stdio/stdout */
65 
66   s1 = vstr_make_base(conf); /* configured size */
67   s2 = malloc(TST_LEN); /* single object */
68   s3 = vstr_make_base(NULL); /* default size */
69   vstr_free_conf(conf);
70   if (!out || !s1 || !s3)
71     exit (EXIT_FAILURE);
72 
73   if (!s2)
74     exit (EXIT_FAILURE);
75 
76   /* print table to say what config we are using ... */
77   vstr_add_fmt(out, out->len,
78                "+${rep_chr:%c%zu}"
79                "+${rep_chr:%c%zu}"
80                "+${rep_chr:%c%zu}"
81                "+${rep_chr:%c%zu}+\n",
82                '=', 17, '=', 18, '=', 18, '=', 18);
83   vstr_add_fmt(out, out->len, "|%16s | %16s | %16s | %16s |\n",
84                "name", "len", "chunks", "chunk size");
85 
86   vstr_add_fmt(out, out->len,
87                "+${rep_chr:%c%zu}"
88                "+${rep_chr:%c%zu}"
89                "+${rep_chr:%c%zu}"
90                "+${rep_chr:%c%zu}+\n",
91                '-', 17, '-', 18, '-', 18, '-', 18);
92   {
93     unsigned int sz = 0;
94 
95     vstr_cntl_conf(s1->conf, VSTR_CNTL_CONF_GET_NUM_BUF_SZ, &sz);
96     vstr_add_fmt(out, out->len,
97                  "|%16s | $16{BKMG.u:%u} | %'16zu | $16{BKMG.u:%u} |\n",
98                  "s1:  conf iovs", (unsigned int) (TST_LEN * TST_NUM),
99                  ((TST_LEN * TST_NUM) / sz) + 1, sz);
100 
101     vstr_add_fmt(out, out->len,
102                  "|%16s | $16{BKMG.u:%u} | %'16zu | $16{BKMG.u:%u} |\n",
103                  "s2:       mmap", (unsigned int) (TST_LEN * TST_NUM),
104                  TST_NUM, TST_LEN);
105 
106     vstr_cntl_conf(s3->conf, VSTR_CNTL_CONF_GET_NUM_BUF_SZ, &sz);
107     vstr_add_fmt(out, out->len,
108                  "|%16s | $16{BKMG.u:%u} | %'16zu | $16{BKMG.u:%u} |\n",
109                  "s3:   def iovs", (unsigned int) (TST_LEN * TST_NUM),
110                  ((TST_LEN * TST_NUM) / sz) + 1, sz);
111   }
112   vstr_add_fmt(out, out->len,
113                "+${rep_chr:%c%zu}"
114                "+${rep_chr:%c%zu}"
115                "+${rep_chr:%c%zu}"
116                "+${rep_chr:%c%zu}+\n",
117                '-', 17, '-', 18, '-', 18, '-', 18);
118 
119   vstr_add_fmt(out, out->len,
120                " Doing tests %'u times with extra malloc of %u:\n",
121                (unsigned int)TST_NUM, TST_MALLOC_EXTRA);
122 
123   err = 0;
124   while (out->len && !err)
125     vstr_sc_write_fd(out, 1, out->len, 1 /* stdout */, &err);
126 
127   TST_HDR_BEG();
128 
129   TST_BEG(1, 1);
130   mal_overhead[tst_count] = malloc(64 - 8);
131   buf_out[0] = 'x';
132   TST_END("single malloc ");
133 
134   for (err = 0; err < 1; ++err)
135     free(mal_overhead[err]);
136 
137   TST_BEG(1, TST_NUM);
138   if (TST_MALLOC_EXTRA)
139     mal_overhead[tst_count] = malloc(TST_MALLOC_EXTRA);
140   buf_out[0] = 'x';
141   if (TST_REUSE)
142     vstr_del(s1, 1, s1->len);
143   vstr_add_rep_chr(s1, s1->len, buf_out[0], TST_LEN);
144   TST_END("s1:  conf iovs");
145 
146   if (TST_FREE)
147   {
148     vstr_del(s1, 1, s1->len);
149     if (TST_MALLOC_EXTRA)
150       for (err = 0; err < TST_NUM; ++err)
151         free(mal_overhead[err]);
152   }
153 
154   TST_BEG(1, TST_NUM);
155   unsigned int off     = (TST_LEN * tst_count);
156   unsigned int new_len = off + TST_LEN;
157 
158   if (TST_MALLOC_EXTRA)
159     mal_overhead[tst_count] = malloc(TST_MALLOC_EXTRA);
160   buf_out[0] = 'x';
161   if (TST_REUSE)
162     off = 0;
163   else
164     s2 = realloc(s2, new_len);
165   if (!s2)
166     goto failed;
167   memset(s2 + off, buf_out[0], TST_LEN);
168   TST_END("s2:     malloc");
169 
170   if (TST_FREE)
171   {
172     free(s2); s2 = NULL;
173     if (TST_MALLOC_EXTRA)
174       for (err = 0; err < TST_NUM; ++err)
175         free(mal_overhead[err]);
176   }
177 
178   TST_BEG(1, TST_NUM);
179   if (TST_MALLOC_EXTRA)
180     mal_overhead[tst_count] = malloc(TST_MALLOC_EXTRA);
181   buf_out[0] = 'x';
182   if (TST_REUSE)
183     vstr_del(s3, 1, s3->len);
184   vstr_add_rep_chr(s3, s3->len, buf_out[0], TST_LEN);
185   TST_END("s3:   def iovs");
186 
187   if (TST_FREE)
188   {
189     vstr_del(s3, 1, s3->len);
190     if (TST_MALLOC_EXTRA)
191       for (err = 0; err < TST_NUM; ++err)
192         free(mal_overhead[err]);
193   }
194 
195   TST_HDR_END();
196 
197   if (s1->conf->malloc_bad || s3->conf->malloc_bad)
198     goto failed;
199 
200   err = 0;
201   while (out->len && !err)
202     vstr_sc_write_fd(out, 1, out->len, 1 /* stdout */, &err);
203 
204   vstr_free_base(out);
205   vstr_free_base(s1);
206   free(s2);
207   vstr_free_base(s3);
208 
209   vstr_exit();
210 
211   exit (EXIT_SUCCESS);
212 
213  failed:
214   err = 0;
215   while (out->len && !err)
216     vstr_sc_write_fd(out, 1, out->len, 2 /* stderr */, &err);
217 
218   vstr_free_base(out);
219   vstr_free_base(s1);
220   free(s2);
221   vstr_free_base(s3);
222 
223   vstr_exit();
224 
225   exit (EXIT_FAILURE);
226 }
227 
228