1/*
2 * Copyright (c) 2000-2001, 2004 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#include <sm/gen.h>
11SM_RCSID("@(#)$Id: b-strcmp.c,v 1.15 2013-11-22 20:51:42 ca Exp $")
12#include <stdio.h>
13#include <stdlib.h>
14#include <unistd.h>
15#include <sys/types.h>
16#include <sm/time.h>
17#include <sm/string.h>
18
19#define toseconds(x, y)	(x.tv_sec - y.tv_sec)
20#define SIZE	512
21#define LOOPS	4000000L	/* initial number of loops */
22#define MAXTIME	30L	/* "maximum" time to run single test */
23
24void fatal __P((char *));
25void purpose __P((void));
26int main __P((int, char *[]));
27
28void
29fatal(str)
30	char *str;
31{
32	perror(str);
33	exit(1);
34}
35
36void
37purpose()
38{
39	printf("This program benchmarks the performance differences between\n");
40	printf("strcasecmp() and sm_strcasecmp().\n");
41	printf("These tests may take several minutes to complete.\n");
42}
43
44int
45main(argc, argv)
46	int argc;
47	char *argv[];
48{
49	long a;
50	int k;
51	bool doit = false;
52	long loops;
53	long j;
54	long one, two;
55	struct timeval t1, t2;
56	char src1[SIZE], src2[SIZE];
57
58# define OPTIONS	"d"
59	while ((k = getopt(argc, argv, OPTIONS)) != -1)
60	{
61		switch ((char) k)
62		{
63		  case 'd':
64			doit = true;
65			break;
66
67		  default:
68			break;
69		}
70	}
71
72	if (!doit)
73	{
74		purpose();
75		printf("If you want to run it, specify -d as option.\n");
76		return 0;
77	}
78
79	/* Run-time comments to the user */
80	purpose();
81	printf("\n");
82	for (k = 0; k < 3; k++)
83	{
84		switch (k)
85		{
86		  case 0:
87			(void) sm_strlcpy(src1, "1234567890", SIZE);
88			(void) sm_strlcpy(src2, "1234567890", SIZE);
89			break;
90		  case 1:
91			(void) sm_strlcpy(src1, "1234567890", SIZE);
92			(void) sm_strlcpy(src2, "1234567891", SIZE);
93			break;
94		  case 2:
95			(void) sm_strlcpy(src1, "1234567892", SIZE);
96			(void) sm_strlcpy(src2, "1234567891", SIZE);
97			break;
98		}
99		printf("Test %d: strcasecmp(%s, %s) versus sm_strcasecmp()\n",
100			k, src1, src2);
101		loops = LOOPS;
102		for (;;)
103		{
104			j = 0;
105			if (gettimeofday(&t1, NULL) < 0)
106				fatal("gettimeofday");
107			for (a = 0; a < loops; a++)
108				j += strcasecmp(src1, src2);
109			if (gettimeofday(&t2, NULL) < 0)
110				fatal("gettimeofday");
111			one = toseconds(t2, t1);
112			printf("\tstrcasecmp() result: %ld seconds [%ld]\n",
113				one, j);
114
115			j = 0;
116			if (gettimeofday(&t1, NULL) < 0)
117				fatal("gettimeofday");
118			for (a = 0; a < loops; a++)
119				j += sm_strcasecmp(src1, src2);
120			if (gettimeofday(&t2, NULL) < 0)
121				fatal("gettimeofday");
122			two = toseconds(t2, t1);
123			printf("\tsm_strcasecmp() result: %ld seconds [%ld]\n",
124				two, j);
125
126			if (abs(one - two) > 2)
127				break;
128			loops += loops;
129			if (loops < 0L || one > MAXTIME)
130			{
131				printf("\t\t** results too close: no decision\n");
132				break;
133			}
134			else
135			{
136				printf("\t\t** results too close redoing test %ld times **\n",
137					loops);
138			}
139		}
140	}
141
142	printf("\n\n");
143	printf("Interpreting the results:\n");
144	printf("\tFor differences larger than 2 seconds, the lower value is\n");
145	printf("\tbetter and that function should be used for performance\n");
146	printf("\treasons.\n\n");
147	printf("This program will re-run the tests when the difference is\n");
148	printf("less than 2 seconds.\n");
149	printf("The result will vary depending on the compiler optimization\n");	printf("level used. Compiling the sendmail libsm library with a\n");
150	printf("better optimization level can change the results.\n");
151	return 0;
152}
153