b-strl.c revision 266527
1/*
2 * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers.
3 *      All rights reserved.
4 *
5 * By using this file, you agree to the terms and conditions set
6 * forth in the LICENSE file which can be found at the top level of
7 * the sendmail distribution.
8 *
9 */
10
11/*
12**  Compile this program using a command line similar to:
13**	cc -O -L../OBJ/libsm -o b-strl b-strl.c -lsm
14**  where "OBJ" is the name of the object directory for the platform
15**  you are compiling on.
16**  Then run the program:
17**	./b-strl
18**  and read the output for results and how to interpret the results.
19*/
20
21#include <sm/gen.h>
22SM_RCSID("@(#)$Id: b-strl.c,v 1.26 2013-11-22 20:51:42 ca Exp $")
23#include <stdio.h>
24#include <stdlib.h>
25#include <unistd.h>
26#include <sys/types.h>
27#include <sm/time.h>
28#include <sm/string.h>
29
30#define SRC_SIZE	512
31#define toseconds(x, y)	(x.tv_sec - y.tv_sec)
32#define LOOPS	4000000L	/* initial number of loops */
33#define MAXTIME	30L	/* "maximum" time to run single test */
34
35void
36fatal(str)
37	char *str;
38{
39	perror(str);
40	exit(1);
41}
42
43void
44purpose()
45{
46	printf("This program benchmarks the performance differences between\n");
47	printf("strlcpy() and sm_strlcpy(), and strlcat() and sm_strlcat().\n");
48	printf("These tests may take several minutes to complete.\n");
49}
50
51int
52main(argc, argv)
53	int argc;
54	char *argv[];
55{
56#if !SM_CONF_STRL
57	printf("The configuration indicates the system needs the libsm\n");
58	printf("versions of strlcpy(3) and strlcat(3). Thus, performing\n");
59	printf("these tests will not be of much use.\n");
60	printf("If your OS has strlcpy(3) and strlcat(3) then set the macro\n");
61	printf("SM_CONF_STRL to 1 in your site.config.m4 file\n");
62	printf("(located in ../devtools/Site) and recompile this program.\n");
63#else /* !SM_CONF_STRL */
64	int ch;
65	long a;
66	bool doit = false;
67	long loops = LOOPS;
68	long one, two;
69	struct timeval t1, t2;
70	char dest[SRC_SIZE], source[SRC_SIZE];
71
72# define OPTIONS	"d"
73	while ((ch = getopt(argc, argv, OPTIONS)) != -1)
74	{
75		switch ((char) ch)
76		{
77		  case 'd':
78			doit = true;
79			break;
80
81		  default:
82			break;
83		}
84	}
85
86	if (!doit)
87	{
88		purpose();
89		printf("If you want to run it, specify -d as option.\n");
90		return 0;
91	}
92
93	/*
94	**  Let's place a small string at the head of dest for
95	**  catenation to happen (it'll be ignored for the copy).
96	*/
97	(void) sm_strlcpy(dest, "a small string at the start! ", SRC_SIZE - 1);
98
99	/*
100	**  Let's place a larger string into source for the catenation and
101	**  the copy.
102	*/
103	(void) strlcpy(source,
104		" This is the longer string that will be used for catenation and copying for the the performace testing. The longer the string being catenated or copied the greater the difference in measureable performance\n",
105		SRC_SIZE - 1);
106
107	/* Run-time comments to the user */
108	purpose();
109	printf("\n");
110	printf("Test 1: strlcat() versus sm_strlcat()\n");
111
112redo_cat:
113	if (gettimeofday(&t1, NULL) < 0)
114		fatal("gettimeofday");
115
116	for (a = 0; a < loops; a++)
117		strlcat(dest, source, SRC_SIZE - 1);
118
119	if (gettimeofday(&t2, NULL) < 0)
120		fatal("gettimeofday");
121
122	printf("\tstrlcat() result: %ld seconds\n", one = toseconds(t2, t1));
123
124	if (gettimeofday(&t1, NULL) < 0)
125		fatal("gettimeofday");
126
127	for (a = 0; a < loops; a++)
128		sm_strlcat(dest, source, SRC_SIZE - 1);
129
130	if (gettimeofday(&t2, NULL) < 0)
131		fatal("gettimeofday");
132
133	printf("\tsm_strlcat() result: %ld seconds\n", two = toseconds(t2, t1));
134
135	if (one - two >= -2 && one - two <= 2)
136	{
137		loops += loops;
138		if (loops < 0L || one > MAXTIME)
139		{
140			printf("\t\t** results too close: no decision\n");
141		}
142		else
143		{
144			printf("\t\t** results too close redoing test %ld times **\n",
145				loops);
146			goto redo_cat;
147		}
148	}
149
150	printf("\n");
151	printf("Test 2: strlcpy() versus sm_strlpy()\n");
152	loops = LOOPS;
153redo_cpy:
154	if (gettimeofday(&t1, NULL) < 0)
155		fatal("gettimeofday");
156
157	for (a = 0; a < loops; a++)
158		strlcpy(dest, source, SRC_SIZE - 1);
159
160	if (gettimeofday(&t2, NULL) < 0)
161		fatal("gettimeofday");
162
163	printf("\tstrlcpy() result: %ld seconds\n", one = toseconds(t2, t1));
164
165	if (gettimeofday(&t1, NULL) < 0)
166		fatal("gettimeofday");
167
168	for (a = 0; a < loops; a++)
169		sm_strlcpy(dest, source, SRC_SIZE - 1);
170
171	if (gettimeofday(&t2, NULL) < 0)
172		fatal("gettimeofday");
173
174	printf("\tsm_strlcpy() result: %ld seconds\n", two = toseconds(t2, t1));
175
176	if (one - two >= -2 && one - two <= 2)
177	{
178		loops += loops;
179		if (loops < 0L || one > MAXTIME)
180		{
181			printf("\t\t** results too close: no decision\n");
182		}
183		else
184		{
185			printf("\t\t** results too close redoing test %ld times **\n",
186				loops);
187			goto redo_cpy;
188		}
189	}
190
191	printf("\n\n");
192	printf("Interpreting the results:\n");
193	printf("\tFor differences larger than 2 seconds, the lower value is\n");
194	printf("\tbetter and that function should be used for performance\n");
195	printf("\treasons.\n\n");
196	printf("This program will re-run the tests when the difference is\n");
197	printf("less than 2 seconds.\n");
198	printf("The result will vary depending on the compiler optimization\n");	printf("level used. Compiling the sendmail libsm library with a\n");
199	printf("better optimization level can change the results.\n");
200#endif /* !SM_CONF_STRL  */
201	return 0;
202}
203