From 0f12359e6238259f303cda178b024f22c1dca69b Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 29 Jun 2026 11:03:09 -0500 Subject: [PATCH 1/2] Remove boundmethod optimization which is no longer performant Baseline: % ./python.exe -m timeit -s 'from statistics import _sum as sm, NormalDist as ND' -s 'data=ND().samples(1000 )' 'sm(data)' 1000 loops, best of 5: 293 usec per loop Patched: % ./python.exe -m timeit -s 'from statistics import _sum as sm, NormalDist as ND' -s 'data=ND().samples(1000)' 'sm(data)' 1000 loops, best of 5: 282 usec per loop --- Lib/statistics.py | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Lib/statistics.py b/Lib/statistics.py index 01ca6c51dafcafe..2b6a43c1a85afd8 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -1486,15 +1486,13 @@ def _sum(data): """ count = 0 types = set() - types_add = types.add partials = {} - partials_get = partials.get for typ, values in groupby(data, type): - types_add(typ) + types.add(typ) for n, d in map(_exact_ratio, values): count += 1 - partials[d] = partials_get(d, 0) + n + partials[d] = partials.get(d, 0) + n if None in partials: # The sum will be a NAN or INF. We can ignore all the finite @@ -1524,12 +1522,11 @@ def _ss(data, c=None): count = 0 types = set() - types_add = types.add sx_partials = defaultdict(int) sxx_partials = defaultdict(int) for typ, values in groupby(data, type): - types_add(typ) + types.add(typ) for n, d in map(_exact_ratio, values): count += 1 sx_partials[d] += n From 2801a30f52223eddacfe4b8b9fc53466f9c150cf Mon Sep 17 00:00:00 2001 From: Raymond Hettinger Date: Mon, 29 Jun 2026 11:09:01 -0500 Subject: [PATCH 2/2] Improve speed and accuracy for the quartic kernel pdf. Reduction in strength from `x ** 2` to `x * x'. The latter is faster and more accurate. Baseline: % ./python.exe -m timeit -s 'from statistics import _kernel_specs as ks' -s 'pdf = ks["quartic"]["pdf"]' 'pdf(0.1234)' 5000000 loops, best of 5: 73 nsec per loop Patched: % ./python.exe -m timeit -s 'from statistics import _kernel_specs as ks' -s 'pdf = ks["quartic"]["pdf"]' 'pdf(0.1234)' 5000000 loops, best of 5: 50.2 nsec per loop --- Lib/statistics.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/statistics.py b/Lib/statistics.py index 2b6a43c1a85afd8..758b5b58848fb98 100644 --- a/Lib/statistics.py +++ b/Lib/statistics.py @@ -894,7 +894,7 @@ def _quartic_invcdf_estimate(p): @register('quartic', 'biweight') def quartic_kernel(): - pdf = lambda t: 15/16 * (1.0 - t * t) ** 2 + pdf = lambda t: 15/16 * (u := 1.0 - t * t) * u cdf = lambda t: sumprod((3/16, -5/8, 15/16, 1/2), (t**5, t**3, t, 1.0)) invcdf = _newton_raphson(_quartic_invcdf_estimate, f=cdf, f_prime=pdf)