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