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

Lines changed: 74 additions & 53 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy