#-*- coding: UTF-8 -*- # # From: http://svn.python.org/projects/sandbox/trunk/decimal/telco/telco.py # Committed by rhettinger. # # Background: # =========== # # http://speleotrove.com/decimal/telco.html # # Sanity check: # ============= # # Download: # # http://svn.python.org/projects/sandbox/trunk/decimal/telco/telco.testb # # In the same directory: # # python telco.py # # Benchmark: # ========== # # Download and unzip: # # http://speleotrove.com/decimal/expon180-1e6b.zip # # In the same directory: # # python telco.py full # """ Telco Benchmark for measuring the performance of decimal calculations A call type indicator, c, is set from the bottom (least significant) bit of the duration (hence c is 0 or 1). A r, r, is determined from the call type. Those calls with c=0 have a low r: 0.0013; the remainder (‘distance calls’) have a ‘premium’ r: 0.00894. (The rates are, very roughly, in Euros or dollar rates per second.) A price, p, for the call is then calculated (p=r*n). This is rounded to exactly 2 fractional digits using round-half-even (Banker’s round to nearest). A basic tax, b, is calculated: b=p*0.0675 (6.75%). This is truncated to exactly 2 fractional digits (round-down), and the total basic tax variable is then incremented (sumB=sumB+b). For distance calls: a distance tax, d, is calculated: d=p*0.0341 (3.41%). This is truncated to exactly 2 fractional digits (round-down), and then the total distance tax variable is incremented (sumD=sumD+d). The total price, t, is calculated (t=p+b, and, if a distance call, t=t+d). The total prices variable is incremented (sumT=sumT+t). The total price, t, is converted to a string, s. """ from struct import unpack from time import perf_counter as time from decimal import * import sys, os, io def benchmark(data): getcontext().rounding = ROUND_DOWN rates = list(map(Decimal, ('0.0013', '0.00894'))) twodig = Decimal('0.01') Banker = Context(rounding=ROUND_HALF_EVEN) basictax = Decimal("0.0675") disttax = Decimal("0.0341") data_index = 0 #infil = io.BytesIO(data) #outfil = io.StringIO() start = time() sumT = Decimal("0") # sum of total prices sumB = Decimal("0") # sum of basic tax sumD = Decimal("0") # sum of 'distance' tax while 1: #datum = infil.read(8) datum = data[data_index: data_index + 8] data_index += 8 if len(datum) < 8: break n, = unpack('>Q', datum) calltype = n & 1 r = rates[calltype] p = Banker.quantize(r * n, twodig) b = p * basictax b = b.quantize(twodig) sumB += b t = p + b if calltype: d = p * disttax d = d.quantize(twodig) sumD += d t += d sumT += t #outfil.write("%s\n" % t) #if test: # print('%6d %1s |%6s %6s %6s |%6s' % (n, 'LD'[calltype], p, b, (not calltype and " " or d), t)) #infil.close() #outfil.close() end = time() #print('\nControl totals:') #print('Actual ', list(map(str, (sumT, sumB, sumD)))) #print('Expected', list(map(str, expected))) print('Elapsed time:', end-start) def main(): # To run the full test with 1,000,000 entries: python telco.py full test = 'full' not in ' '.join(sys.argv[1:]).lower() if test: filename = "telco.testb" expected = list(map(Decimal, "8.91 0.50 0.22".split())) print(" Time Rate | Price Btax Dtax | Output") print("------------+----------------------+--------") else: filename = "expon180.1e6b" if not os.access(filename, os.F_OK): print("You must download and unzip the test file from: " "http://speleotrove.com/decimal/expon180-1e6b.zip") sys.exit(-1) expected = list(map(Decimal, "1004737.58 57628.30 25042.17".split())) with open(filename, "rb") as fp: data = fp.read() for run in range(5): benchmark(data) print("") os.system("grep -E -i 'cpu|ctx' /proc/%s/status" % os.getpid()) if __name__ == "__main__": main()