xref: /freebsd/contrib/sendmail/libsm/b-strl.c (revision 40a8ac8f62b535d30349faf28cf47106b7041b83)
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>
22 SM_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 
35 void
36 fatal(str)
37 	char *str;
38 {
39 	perror(str);
40 	exit(1);
41 }
42 
43 void
44 purpose()
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 
51 int
52 main(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 
112 redo_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;
153 redo_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