Skip to content

Commit 71c82af

Browse files
committed
v3
1 parent 93b69cd commit 71c82af

File tree

1 file changed

+45
-25
lines changed

1 file changed

+45
-25
lines changed

Objects/listobject.c

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1902,28 +1902,28 @@ abinarysort(MergeState *ms, const sortslice *ss, Py_ssize_t n, Py_ssize_t ok, in
19021902

19031903
Py_ssize_t M, L, R;
19041904
Py_ssize_t nsorted = ok;
1905-
Py_ssize_t diff_new;
1906-
Py_ssize_t diff = ok; // jump (jump out on 1st loop to not kick in)
1907-
Py_ssize_t last = ok >> 1; // mid point (simple binary on 1st loop)
1908-
Py_ssize_t ns = 0; // number of successes (a bit of head start)
1905+
Py_ssize_t last = ok >> 1;
1906+
Py_ssize_t std = ok >> 2;
1907+
Py_ssize_t mu = last;
1908+
Py_ssize_t nb = 0; // badness of fit
19091909

19101910
if (adapt) {
19111911
for (; ok < n; ++ok) {
19121912
pivot = a[ok];
19131913

1914-
IFLT(pivot, a[last]) {
1914+
IFLT(pivot, a[mu]) {
19151915
L = 0;
1916-
R = last;
1916+
R = mu;
19171917
if (L < R) {
19181918
// To not affect diff for measure counting
1919-
diff_new = diff + (diff == 0);
1920-
M = R - diff_new;
1919+
std += (std == 0);
1920+
M = R - std;
19211921
if (M < L)
19221922
M = L;
19231923
IFLT(pivot, a[M]) {
19241924
R = M;
19251925
if (L < R) {
1926-
M = R - diff_new;
1926+
M = R - std;
19271927
if (M < L)
19281928
M = L;
19291929
IFLT(pivot, a[M])
@@ -1938,10 +1938,10 @@ abinarysort(MergeState *ms, const sortslice *ss, Py_ssize_t n, Py_ssize_t ok, in
19381938
}
19391939
}
19401940
else {
1941-
L = last + 1;
1941+
L = mu + 1;
19421942
R = ok;
19431943
if (L < R) {
1944-
M = L + diff;
1944+
M = L + std;
19451945
if (M >= R)
19461946
M = R - 1;
19471947
IFLT(pivot, a[M]) {
@@ -1950,7 +1950,7 @@ abinarysort(MergeState *ms, const sortslice *ss, Py_ssize_t n, Py_ssize_t ok, in
19501950
else {
19511951
L = M + 1;
19521952
if (L < R) {
1953-
M = L + diff;
1953+
M = L + std;
19541954
if (M >= R)
19551955
M = R - 1;
19561956
IFLT(pivot, a[M])
@@ -1982,9 +1982,10 @@ abinarysort(MergeState *ms, const sortslice *ss, Py_ssize_t n, Py_ssize_t ok, in
19821982
}
19831983

19841984
// Update Adaptive runvars
1985-
diff_new = L < last ? last - L : L - last;
1986-
ns += diff_new < diff ? diff - diff_new : diff_new - diff;
1987-
diff = diff_new;
1985+
std = L < mu ? mu - L : L - mu;
1986+
nb += std;
1987+
mu = L + L - last;
1988+
mu = mu < 0 ? 0 : mu > ok ? ok : mu;
19881989
last = L;
19891990
}
19901991
}
@@ -2014,15 +2015,16 @@ abinarysort(MergeState *ms, const sortslice *ss, Py_ssize_t n, Py_ssize_t ok, in
20142015
}
20152016

20162017
// Update Adaptive runvars
2017-
diff_new = L < last ? last - L : L - last;
2018-
ns += diff_new < diff ? diff - diff_new : diff_new - diff;
2019-
diff = diff_new;
2018+
std = L < mu ? mu - L : L - mu;
2019+
nb += std;
2020+
mu = L + L - last;
2021+
mu = mu < 0 ? 0 : mu > ok ? ok : mu;
20202022
last = L;
20212023
}
20222024
}
20232025

20242026
// Return Adaptivity measure (max 1000)
2025-
return ns * 2000 / ((n + 2 * nsorted - 1) * n);
2027+
return nb * 2000 / ((n + 2 * nsorted - 1) * n);
20262028

20272029
fail:
20282030
return -1;
@@ -3216,10 +3218,12 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse)
32163218
/* March over the array once, left to right, finding natural runs,
32173219
* and extending short natural runs to minrun elements.
32183220
*/
3219-
int binary_adapt = 1;
32203221
// NOTE: Could turn on based on minlen or comparison type
3222+
int binary_adapt = ms.listlen >= 100;
32213223
if (binary_adapt) {
32223224
int adapt = 0; // do not run binarysort adaptivity on 1st run
3225+
Py_ssize_t cs = 0;
3226+
Py_ssize_t cd = 1;
32233227
do {
32243228
/* Identify next run. */
32253229
Py_ssize_t n;
@@ -3231,11 +3235,27 @@ list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse)
32313235
if (n < minrun) {
32323236
const Py_ssize_t force = nremaining <= minrun ?
32333237
nremaining : minrun;
3234-
Py_ssize_t bres;
3235-
bres = abinarysort(&ms, &lo, force, n, adapt);
3236-
if (bres < 0)
3237-
goto fail;
3238-
adapt = bres < 125;
3238+
if (cs) {
3239+
if (binarysort(&ms, &lo, force, n) < 0)
3240+
goto fail;
3241+
cs -= 1;
3242+
}
3243+
else {
3244+
Py_ssize_t bres;
3245+
bres = abinarysort(&ms, &lo, force, n, adapt);
3246+
if (bres < 0)
3247+
goto fail;
3248+
adapt = bres < 250;
3249+
if (adapt) {
3250+
cd = 1;
3251+
}
3252+
else {
3253+
cd += 2;
3254+
if (cd > 11)
3255+
cd = 11;
3256+
cs = cd;
3257+
}
3258+
}
32393259
n = force;
32403260
}
32413261
else {

0 commit comments

Comments
 (0)