190792Sgshapiro/*
2261194Sgshapiro * Copyright (c) 2000-2001 Proofpoint, Inc. and its suppliers.
390792Sgshapiro *      All rights reserved.
490792Sgshapiro *
590792Sgshapiro * By using this file, you agree to the terms and conditions set
690792Sgshapiro * forth in the LICENSE file which can be found at the top level of
790792Sgshapiro * the sendmail distribution.
890792Sgshapiro *
990792Sgshapiro */
1090792Sgshapiro
1190792Sgshapiro/*
1290792Sgshapiro**  Compile this program using a command line similar to:
1390792Sgshapiro**	cc -O -L../OBJ/libsm -o b-strl b-strl.c -lsm
1490792Sgshapiro**  where "OBJ" is the name of the object directory for the platform
1590792Sgshapiro**  you are compiling on.
1690792Sgshapiro**  Then run the program:
1790792Sgshapiro**	./b-strl
1890792Sgshapiro**  and read the output for results and how to interpret the results.
1990792Sgshapiro*/
2090792Sgshapiro
2190792Sgshapiro#include <sm/gen.h>
22266527SgshapiroSM_RCSID("@(#)$Id: b-strl.c,v 1.26 2013-11-22 20:51:42 ca Exp $")
2390792Sgshapiro#include <stdio.h>
2490792Sgshapiro#include <stdlib.h>
2590792Sgshapiro#include <unistd.h>
2690792Sgshapiro#include <sys/types.h>
27157001Sgshapiro#include <sm/time.h>
2890792Sgshapiro#include <sm/string.h>
2990792Sgshapiro
3090792Sgshapiro#define SRC_SIZE	512
3190792Sgshapiro#define toseconds(x, y)	(x.tv_sec - y.tv_sec)
3290792Sgshapiro#define LOOPS	4000000L	/* initial number of loops */
3390792Sgshapiro#define MAXTIME	30L	/* "maximum" time to run single test */
3490792Sgshapiro
3590792Sgshapirovoid
3690792Sgshapirofatal(str)
3790792Sgshapiro	char *str;
3890792Sgshapiro{
3990792Sgshapiro	perror(str);
4090792Sgshapiro	exit(1);
4190792Sgshapiro}
4290792Sgshapiro
4390792Sgshapirovoid
4490792Sgshapiropurpose()
4590792Sgshapiro{
4690792Sgshapiro	printf("This program benchmarks the performance differences between\n");
4790792Sgshapiro	printf("strlcpy() and sm_strlcpy(), and strlcat() and sm_strlcat().\n");
4890792Sgshapiro	printf("These tests may take several minutes to complete.\n");
4990792Sgshapiro}
5090792Sgshapiro
5190792Sgshapiroint
5290792Sgshapiromain(argc, argv)
5390792Sgshapiro	int argc;
5490792Sgshapiro	char *argv[];
5590792Sgshapiro{
5690792Sgshapiro#if !SM_CONF_STRL
5790792Sgshapiro	printf("The configuration indicates the system needs the libsm\n");
5890792Sgshapiro	printf("versions of strlcpy(3) and strlcat(3). Thus, performing\n");
5990792Sgshapiro	printf("these tests will not be of much use.\n");
6090792Sgshapiro	printf("If your OS has strlcpy(3) and strlcat(3) then set the macro\n");
6190792Sgshapiro	printf("SM_CONF_STRL to 1 in your site.config.m4 file\n");
6290792Sgshapiro	printf("(located in ../devtools/Site) and recompile this program.\n");
6390792Sgshapiro#else /* !SM_CONF_STRL */
6490792Sgshapiro	int ch;
6590792Sgshapiro	long a;
6690792Sgshapiro	bool doit = false;
6790792Sgshapiro	long loops = LOOPS;
6890792Sgshapiro	long one, two;
6990792Sgshapiro	struct timeval t1, t2;
7090792Sgshapiro	char dest[SRC_SIZE], source[SRC_SIZE];
7190792Sgshapiro
7290792Sgshapiro# define OPTIONS	"d"
7390792Sgshapiro	while ((ch = getopt(argc, argv, OPTIONS)) != -1)
7490792Sgshapiro	{
7590792Sgshapiro		switch ((char) ch)
7690792Sgshapiro		{
7790792Sgshapiro		  case 'd':
7890792Sgshapiro			doit = true;
7990792Sgshapiro			break;
8090792Sgshapiro
8190792Sgshapiro		  default:
8290792Sgshapiro			break;
8390792Sgshapiro		}
8490792Sgshapiro	}
8590792Sgshapiro
8690792Sgshapiro	if (!doit)
8790792Sgshapiro	{
8890792Sgshapiro		purpose();
8990792Sgshapiro		printf("If you want to run it, specify -d as option.\n");
9090792Sgshapiro		return 0;
9190792Sgshapiro	}
9290792Sgshapiro
9390792Sgshapiro	/*
9490792Sgshapiro	**  Let's place a small string at the head of dest for
9590792Sgshapiro	**  catenation to happen (it'll be ignored for the copy).
9690792Sgshapiro	*/
9790792Sgshapiro	(void) sm_strlcpy(dest, "a small string at the start! ", SRC_SIZE - 1);
9890792Sgshapiro
9990792Sgshapiro	/*
10090792Sgshapiro	**  Let's place a larger string into source for the catenation and
10190792Sgshapiro	**  the copy.
10290792Sgshapiro	*/
10390792Sgshapiro	(void) strlcpy(source,
10490792Sgshapiro		" 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",
10590792Sgshapiro		SRC_SIZE - 1);
10690792Sgshapiro
10790792Sgshapiro	/* Run-time comments to the user */
10890792Sgshapiro	purpose();
10990792Sgshapiro	printf("\n");
11090792Sgshapiro	printf("Test 1: strlcat() versus sm_strlcat()\n");
11190792Sgshapiro
11290792Sgshapiroredo_cat:
11390792Sgshapiro	if (gettimeofday(&t1, NULL) < 0)
11490792Sgshapiro		fatal("gettimeofday");
11590792Sgshapiro
11690792Sgshapiro	for (a = 0; a < loops; a++)
11790792Sgshapiro		strlcat(dest, source, SRC_SIZE - 1);
11890792Sgshapiro
11990792Sgshapiro	if (gettimeofday(&t2, NULL) < 0)
12090792Sgshapiro		fatal("gettimeofday");
12190792Sgshapiro
12290792Sgshapiro	printf("\tstrlcat() result: %ld seconds\n", one = toseconds(t2, t1));
12390792Sgshapiro
12490792Sgshapiro	if (gettimeofday(&t1, NULL) < 0)
12590792Sgshapiro		fatal("gettimeofday");
12690792Sgshapiro
12790792Sgshapiro	for (a = 0; a < loops; a++)
12890792Sgshapiro		sm_strlcat(dest, source, SRC_SIZE - 1);
12990792Sgshapiro
13090792Sgshapiro	if (gettimeofday(&t2, NULL) < 0)
13190792Sgshapiro		fatal("gettimeofday");
13290792Sgshapiro
13390792Sgshapiro	printf("\tsm_strlcat() result: %ld seconds\n", two = toseconds(t2, t1));
13490792Sgshapiro
13590792Sgshapiro	if (one - two >= -2 && one - two <= 2)
13690792Sgshapiro	{
13790792Sgshapiro		loops += loops;
13890792Sgshapiro		if (loops < 0L || one > MAXTIME)
13990792Sgshapiro		{
14090792Sgshapiro			printf("\t\t** results too close: no decision\n");
14190792Sgshapiro		}
14290792Sgshapiro		else
14390792Sgshapiro		{
14490792Sgshapiro			printf("\t\t** results too close redoing test %ld times **\n",
14590792Sgshapiro				loops);
14690792Sgshapiro			goto redo_cat;
14790792Sgshapiro		}
14890792Sgshapiro	}
14990792Sgshapiro
15090792Sgshapiro	printf("\n");
15190792Sgshapiro	printf("Test 2: strlcpy() versus sm_strlpy()\n");
15290792Sgshapiro	loops = LOOPS;
15390792Sgshapiroredo_cpy:
15490792Sgshapiro	if (gettimeofday(&t1, NULL) < 0)
15590792Sgshapiro		fatal("gettimeofday");
15690792Sgshapiro
15790792Sgshapiro	for (a = 0; a < loops; a++)
15890792Sgshapiro		strlcpy(dest, source, SRC_SIZE - 1);
15990792Sgshapiro
16090792Sgshapiro	if (gettimeofday(&t2, NULL) < 0)
16190792Sgshapiro		fatal("gettimeofday");
16290792Sgshapiro
16390792Sgshapiro	printf("\tstrlcpy() result: %ld seconds\n", one = toseconds(t2, t1));
16490792Sgshapiro
16590792Sgshapiro	if (gettimeofday(&t1, NULL) < 0)
16690792Sgshapiro		fatal("gettimeofday");
16790792Sgshapiro
16890792Sgshapiro	for (a = 0; a < loops; a++)
16990792Sgshapiro		sm_strlcpy(dest, source, SRC_SIZE - 1);
17090792Sgshapiro
17190792Sgshapiro	if (gettimeofday(&t2, NULL) < 0)
17290792Sgshapiro		fatal("gettimeofday");
17390792Sgshapiro
17490792Sgshapiro	printf("\tsm_strlcpy() result: %ld seconds\n", two = toseconds(t2, t1));
17590792Sgshapiro
17690792Sgshapiro	if (one - two >= -2 && one - two <= 2)
17790792Sgshapiro	{
17890792Sgshapiro		loops += loops;
17990792Sgshapiro		if (loops < 0L || one > MAXTIME)
18090792Sgshapiro		{
18190792Sgshapiro			printf("\t\t** results too close: no decision\n");
18290792Sgshapiro		}
18390792Sgshapiro		else
18490792Sgshapiro		{
18590792Sgshapiro			printf("\t\t** results too close redoing test %ld times **\n",
18690792Sgshapiro				loops);
18790792Sgshapiro			goto redo_cpy;
18890792Sgshapiro		}
18990792Sgshapiro	}
19090792Sgshapiro
19190792Sgshapiro	printf("\n\n");
19290792Sgshapiro	printf("Interpreting the results:\n");
19390792Sgshapiro	printf("\tFor differences larger than 2 seconds, the lower value is\n");
19490792Sgshapiro	printf("\tbetter and that function should be used for performance\n");
19590792Sgshapiro	printf("\treasons.\n\n");
19690792Sgshapiro	printf("This program will re-run the tests when the difference is\n");
19790792Sgshapiro	printf("less than 2 seconds.\n");
19890792Sgshapiro	printf("The result will vary depending on the compiler optimization\n");	printf("level used. Compiling the sendmail libsm library with a\n");
19990792Sgshapiro	printf("better optimization level can change the results.\n");
20090792Sgshapiro#endif /* !SM_CONF_STRL  */
20190792Sgshapiro	return 0;
20290792Sgshapiro}
203