Skip to content

Commit b39f65a

Browse files
gh-108346: Fix failed benchmark in decimal (#108353)
Fix benchmark in decimal to work again after the int str conversion limits.
1 parent 388d91c commit b39f65a

File tree

1 file changed

+74
-53
lines changed

1 file changed

+74
-53
lines changed

Modules/_decimal/tests/bench.py

+74-53
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77

88

99
import time
10+
import sys
11+
from functools import wraps
1012
from test.support.import_helper import import_fresh_module
1113

1214
C = import_fresh_module('decimal', fresh=['_decimal'])
@@ -64,66 +66,85 @@ def factorial(n, m):
6466
else:
6567
return factorial(n, (n+m)//2) * factorial((n+m)//2 + 1, m)
6668

69+
# Fix failed test cases caused by CVE-2020-10735 patch.
70+
# See gh-95778 for details.
71+
def increase_int_max_str_digits(maxdigits):
72+
def _increase_int_max_str_digits(func, maxdigits=maxdigits):
73+
@wraps(func)
74+
def wrapper(*args, **kwargs):
75+
previous_int_limit = sys.get_int_max_str_digits()
76+
sys.set_int_max_str_digits(maxdigits)
77+
ans = func(*args, **kwargs)
78+
sys.set_int_max_str_digits(previous_int_limit)
79+
return ans
80+
return wrapper
81+
return _increase_int_max_str_digits
82+
83+
def test_calc_pi():
84+
print("\n# ======================================================================")
85+
print("# Calculating pi, 10000 iterations")
86+
print("# ======================================================================\n")
87+
88+
to_benchmark = [pi_float, pi_decimal]
89+
if C is not None:
90+
to_benchmark.insert(1, pi_cdecimal)
91+
92+
for prec in [9, 19]:
93+
print("\nPrecision: %d decimal digits\n" % prec)
94+
for func in to_benchmark:
95+
start = time.time()
96+
if C is not None:
97+
C.getcontext().prec = prec
98+
P.getcontext().prec = prec
99+
for i in range(10000):
100+
x = func()
101+
print("%s:" % func.__name__.replace("pi_", ""))
102+
print("result: %s" % str(x))
103+
print("time: %fs\n" % (time.time()-start))
104+
105+
@increase_int_max_str_digits(maxdigits=10000000)
106+
def test_factorial():
107+
print("\n# ======================================================================")
108+
print("# Factorial")
109+
print("# ======================================================================\n")
67110

68-
print("\n# ======================================================================")
69-
print("# Calculating pi, 10000 iterations")
70-
print("# ======================================================================\n")
71-
72-
to_benchmark = [pi_float, pi_decimal]
73-
if C is not None:
74-
to_benchmark.insert(1, pi_cdecimal)
75-
76-
for prec in [9, 19]:
77-
print("\nPrecision: %d decimal digits\n" % prec)
78-
for func in to_benchmark:
79-
start = time.time()
80-
if C is not None:
81-
C.getcontext().prec = prec
82-
P.getcontext().prec = prec
83-
for i in range(10000):
84-
x = func()
85-
print("%s:" % func.__name__.replace("pi_", ""))
86-
print("result: %s" % str(x))
87-
print("time: %fs\n" % (time.time()-start))
88-
89-
90-
print("\n# ======================================================================")
91-
print("# Factorial")
92-
print("# ======================================================================\n")
93-
94-
if C is not None:
95-
c = C.getcontext()
96-
c.prec = C.MAX_PREC
97-
c.Emax = C.MAX_EMAX
98-
c.Emin = C.MIN_EMIN
111+
if C is not None:
112+
c = C.getcontext()
113+
c.prec = C.MAX_PREC
114+
c.Emax = C.MAX_EMAX
115+
c.Emin = C.MIN_EMIN
99116

100-
for n in [100000, 1000000]:
117+
for n in [100000, 1000000]:
101118

102-
print("n = %d\n" % n)
119+
print("n = %d\n" % n)
103120

104-
if C is not None:
105-
# C version of decimal
121+
if C is not None:
122+
# C version of decimal
123+
start_calc = time.time()
124+
x = factorial(C.Decimal(n), 0)
125+
end_calc = time.time()
126+
start_conv = time.time()
127+
sx = str(x)
128+
end_conv = time.time()
129+
print("cdecimal:")
130+
print("calculation time: %fs" % (end_calc-start_calc))
131+
print("conversion time: %fs\n" % (end_conv-start_conv))
132+
133+
# Python integers
106134
start_calc = time.time()
107-
x = factorial(C.Decimal(n), 0)
135+
y = factorial(n, 0)
108136
end_calc = time.time()
109137
start_conv = time.time()
110-
sx = str(x)
111-
end_conv = time.time()
112-
print("cdecimal:")
113-
print("calculation time: %fs" % (end_calc-start_calc))
114-
print("conversion time: %fs\n" % (end_conv-start_conv))
138+
sy = str(y)
139+
end_conv = time.time()
115140

116-
# Python integers
117-
start_calc = time.time()
118-
y = factorial(n, 0)
119-
end_calc = time.time()
120-
start_conv = time.time()
121-
sy = str(y)
122-
end_conv = time.time()
141+
print("int:")
142+
print("calculation time: %fs" % (end_calc-start_calc))
143+
print("conversion time: %fs\n\n" % (end_conv-start_conv))
123144

124-
print("int:")
125-
print("calculation time: %fs" % (end_calc-start_calc))
126-
print("conversion time: %fs\n\n" % (end_conv-start_conv))
145+
if C is not None:
146+
assert(sx == sy)
127147

128-
if C is not None:
129-
assert(sx == sy)
148+
if __name__ == "__main__":
149+
test_calc_pi()
150+
test_factorial()

0 commit comments

Comments
 (0)