1 #! /usr/bin/env python3 2 3 """ 4 "PYSTONE" Benchmark Program 5 6 Version: Python/1.2 (corresponds to C/1.1 plus 3 Pystone fixes) 7 8 Author: Reinhold P. Weicker, CACM Vol 27, No 10, 10/84 pg. 1013. 9 10 Translated from ADA to C by Rick Richardson. 11 Every method to preserve ADA-likeness has been used, 12 at the expense of C-ness. 13 14 Translated from C to Python by Guido van Rossum. 15 16 Version History: 17 18 Version 1.1 corrects two bugs in version 1.0: 19 20 First, it leaked memory: in Proc1(), NextRecord ends 21 up having a pointer to itself. I have corrected this 22 by zapping NextRecord.PtrComp at the end of Proc1(). 23 24 Second, Proc3() used the operator != to compare a 25 record to None. This is rather inefficient and not 26 true to the intention of the original benchmark (where 27 a pointer comparison to None is intended; the != 28 operator attempts to find a method __cmp__ to do value 29 comparison of the record). Version 1.1 runs 5-10 30 percent faster than version 1.0, so benchmark figures 31 of different versions can't be compared directly. 32 33 Version 1.2 changes the division to floor division. 34 35 Under Python 3 version 1.1 would use the normal division 36 operator, resulting in some of the operations mistakenly 37 yielding floats. Version 1.2 instead uses floor division 38 making the benchmark an integer benchmark again. 39 40 """ 41 42 LOOPS = 50000 43 44 from time import time 45 46 __version__ = "1.2" 47 48 [Ident1, Ident2, Ident3, Ident4, Ident5] = range(1, 6) 49 50 class Record: 51 52 def __init__(self, PtrComp = None, Discr = 0, EnumComp = 0, 53 IntComp = 0, StringComp = 0): 54 self.PtrComp = PtrComp 55 self.Discr = Discr 56 self.EnumComp = EnumComp 57 self.IntComp = IntComp 58 self.StringComp = StringComp 59 60 def copy(self): 61 return Record(self.PtrComp, self.Discr, self.EnumComp, 62 self.IntComp, self.StringComp) 63 64 TRUE = 1 65 FALSE = 0 66 67 def main(loops=LOOPS): 68 benchtime, stones = pystones(loops) 69 print("Pystone(%s) time for %d passes = %g" % \ 70 (__version__, loops, benchtime)) 71 print("This machine benchmarks at %g pystones/second" % stones) 72 73 74 def pystones(loops=LOOPS): 75 return Proc0(loops) 76 77 IntGlob = 0 78 BoolGlob = FALSE 79 Char1Glob = '\0' 80 Char2Glob = '\0' 81 Array1Glob = [0]*51 82 Array2Glob = [x[:] for x in [Array1Glob]*51] 83 PtrGlb = None 84 PtrGlbNext = None 85 86 def Proc0(loops=LOOPS): 87 global IntGlob 88 global BoolGlob 89 global Char1Glob 90 global Char2Glob 91 global Array1Glob 92 global Array2Glob 93 global PtrGlb 94 global PtrGlbNext 95 96 starttime = time() 97 for i in range(loops): 98 pass 99 nulltime = time() - starttime 100 101 PtrGlbNext = Record() 102 PtrGlb = Record() 103 PtrGlb.PtrComp = PtrGlbNext 104 PtrGlb.Discr = Ident1 105 PtrGlb.EnumComp = Ident3 106 PtrGlb.IntComp = 40 107 PtrGlb.StringComp = "DHRYSTONE PROGRAM, SOME STRING" 108 String1Loc = "DHRYSTONE PROGRAM, 1'ST STRING" 109 Array2Glob[8][7] = 10 110 111 starttime = time() 112 113 for i in range(loops): 114 Proc5() 115 Proc4() 116 IntLoc1 = 2 117 IntLoc2 = 3 118 String2Loc = "DHRYSTONE PROGRAM, 2'ND STRING" 119 EnumLoc = Ident2 120 BoolGlob = not Func2(String1Loc, String2Loc) 121 while IntLoc1 < IntLoc2: 122 IntLoc3 = 5 * IntLoc1 - IntLoc2 123 IntLoc3 = Proc7(IntLoc1, IntLoc2) 124 IntLoc1 = IntLoc1 + 1 125 Proc8(Array1Glob, Array2Glob, IntLoc1, IntLoc3) 126 PtrGlb = Proc1(PtrGlb) 127 CharIndex = 'A' 128 while CharIndex <= Char2Glob: 129 if EnumLoc == Func1(CharIndex, 'C'): 130 EnumLoc = Proc6(Ident1) 131 CharIndex = chr(ord(CharIndex)+1) 132 IntLoc3 = IntLoc2 * IntLoc1 133 IntLoc2 = IntLoc3 // IntLoc1 134 IntLoc2 = 7 * (IntLoc3 - IntLoc2) - IntLoc1 135 IntLoc1 = Proc2(IntLoc1) 136 137 benchtime = time() - starttime - nulltime 138 if benchtime == 0.0: 139 loopsPerBenchtime = 0.0 140 else: 141 loopsPerBenchtime = (loops / benchtime) 142 return benchtime, loopsPerBenchtime 143 144 def Proc1(PtrParIn): 145 PtrParIn.PtrComp = NextRecord = PtrGlb.copy() 146 PtrParIn.IntComp = 5 147 NextRecord.IntComp = PtrParIn.IntComp 148 NextRecord.PtrComp = PtrParIn.PtrComp 149 NextRecord.PtrComp = Proc3(NextRecord.PtrComp) 150 if NextRecord.Discr == Ident1: 151 NextRecord.IntComp = 6 152 NextRecord.EnumComp = Proc6(PtrParIn.EnumComp) 153 NextRecord.PtrComp = PtrGlb.PtrComp 154 NextRecord.IntComp = Proc7(NextRecord.IntComp, 10) 155 else: 156 PtrParIn = NextRecord.copy() 157 NextRecord.PtrComp = None 158 return PtrParIn 159 160 def Proc2(IntParIO): 161 IntLoc = IntParIO + 10 162 while 1: 163 if Char1Glob == 'A': 164 IntLoc = IntLoc - 1 165 IntParIO = IntLoc - IntGlob 166 EnumLoc = Ident1 167 if EnumLoc == Ident1: 168 break 169 return IntParIO 170 171 def Proc3(PtrParOut): 172 global IntGlob 173 174 if PtrGlb is not None: 175 PtrParOut = PtrGlb.PtrComp 176 else: 177 IntGlob = 100 178 PtrGlb.IntComp = Proc7(10, IntGlob) 179 return PtrParOut 180 181 def Proc4(): 182 global Char2Glob 183 184 BoolLoc = Char1Glob == 'A' 185 BoolLoc = BoolLoc or BoolGlob 186 Char2Glob = 'B' 187 188 def Proc5(): 189 global Char1Glob 190 global BoolGlob 191 192 Char1Glob = 'A' 193 BoolGlob = FALSE 194 195 def Proc6(EnumParIn): 196 EnumParOut = EnumParIn 197 if not Func3(EnumParIn): 198 EnumParOut = Ident4 199 if EnumParIn == Ident1: 200 EnumParOut = Ident1 201 elif EnumParIn == Ident2: 202 if IntGlob > 100: 203 EnumParOut = Ident1 204 else: 205 EnumParOut = Ident4 206 elif EnumParIn == Ident3: 207 EnumParOut = Ident2 208 elif EnumParIn == Ident4: 209 pass 210 elif EnumParIn == Ident5: 211 EnumParOut = Ident3 212 return EnumParOut 213 214 def Proc7(IntParI1, IntParI2): 215 IntLoc = IntParI1 + 2 216 IntParOut = IntParI2 + IntLoc 217 return IntParOut 218 219 def Proc8(Array1Par, Array2Par, IntParI1, IntParI2): 220 global IntGlob 221 222 IntLoc = IntParI1 + 5 223 Array1Par[IntLoc] = IntParI2 224 Array1Par[IntLoc+1] = Array1Par[IntLoc] 225 Array1Par[IntLoc+30] = IntLoc 226 for IntIndex in range(IntLoc, IntLoc+2): 227 Array2Par[IntLoc][IntIndex] = IntLoc 228 Array2Par[IntLoc][IntLoc-1] = Array2Par[IntLoc][IntLoc-1] + 1 229 Array2Par[IntLoc+20][IntLoc] = Array1Par[IntLoc] 230 IntGlob = 5 231 232 def Func1(CharPar1, CharPar2): 233 CharLoc1 = CharPar1 234 CharLoc2 = CharLoc1 235 if CharLoc2 != CharPar2: 236 return Ident1 237 else: 238 return Ident2 239 240 def Func2(StrParI1, StrParI2): 241 IntLoc = 1 242 while IntLoc <= 1: 243 if Func1(StrParI1[IntLoc], StrParI2[IntLoc+1]) == Ident1: 244 CharLoc = 'A' 245 IntLoc = IntLoc + 1 246 if CharLoc >= 'W' and CharLoc <= 'Z': 247 IntLoc = 7 248 if CharLoc == 'X': 249 return TRUE 250 else: 251 if StrParI1 > StrParI2: 252 IntLoc = IntLoc + 7 253 return TRUE 254 else: 255 return FALSE 256 257 def Func3(EnumParIn): 258 EnumLoc = EnumParIn 259 if EnumLoc == Ident3: return TRUE 260 return FALSE 261 262 if __name__ == '__main__': 263 import sys 264 def error(msg): 265 print(msg, end=' ', file=sys.stderr) 266 print("usage: %s [number_of_loops]" % sys.argv[0], file=sys.stderr) 267 sys.exit(100) 268 nargs = len(sys.argv) - 1 269 if nargs > 1: 270 error("%d arguments are too many;" % nargs) 271 elif nargs == 1: 272 try: loops = int(sys.argv[1]) 273 except ValueError: 274 error("Invalid argument %r;" % sys.argv[1]) 275 else: 276 loops = LOOPS 277 main(loops) 278