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 performance 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