Commit 464d89b3 authored by Raymond Hettinger's avatar Raymond Hettinger

Issue #16398: Optimize deque.rotate()

parent eb9e885f
...@@ -221,6 +221,9 @@ Library ...@@ -221,6 +221,9 @@ Library
duplication. Thanks to Ronan Lamy for the report and taking an initial stab duplication. Thanks to Ronan Lamy for the report and taking an initial stab
at the problem. at the problem.
- Issue #16398: Optimize deque.rotate() so that it only moves pointers
and doesn't touch the underlying data with increfs and decrefs.
- Issue #16900: Issue a ResourceWarning when an ssl socket is left unclosed. - Issue #16900: Issue a ResourceWarning when an ssl socket is left unclosed.
- Issue #13899: \A, \Z, and \B now correctly match the A, Z, and B literals - Issue #13899: \A, \Z, and \B now correctly match the A, Z, and B literals
......
...@@ -414,9 +414,10 @@ static int ...@@ -414,9 +414,10 @@ static int
_deque_rotate(dequeobject *deque, Py_ssize_t n) _deque_rotate(dequeobject *deque, Py_ssize_t n)
{ {
Py_ssize_t i, len=deque->len, halflen=(len+1)>>1; Py_ssize_t i, len=deque->len, halflen=(len+1)>>1;
PyObject *item, *rv; PyObject *item;
block *prevblock, *leftblock, *rightblock;
if (len == 0) if (len <= 1)
return 0; return 0;
if (n > halflen || n < -halflen) { if (n > halflen || n < -halflen) {
n %= len; n %= len;
...@@ -426,23 +427,66 @@ _deque_rotate(dequeobject *deque, Py_ssize_t n) ...@@ -426,23 +427,66 @@ _deque_rotate(dequeobject *deque, Py_ssize_t n)
n += len; n += len;
} }
assert(deque->len > 1);
deque->state++;
leftblock = deque->leftblock;
rightblock = deque->rightblock;
for (i=0 ; i<n ; i++) { for (i=0 ; i<n ; i++) {
item = deque_pop(deque, NULL); item = rightblock->data[deque->rightindex];
assert (item != NULL); assert (item != NULL);
rv = deque_appendleft(deque, item); deque->rightindex--;
Py_DECREF(item); if (deque->rightindex == -1) {
if (rv == NULL) assert(rightblock != NULL);
return -1; prevblock = rightblock->leftlink;
Py_DECREF(rv); assert(leftblock != rightblock);
freeblock(rightblock);
prevblock->rightlink = NULL;
deque->rightblock = rightblock = prevblock;
deque->rightindex = BLOCKLEN - 1;
}
if (deque->leftindex == 0) {
block *b = newblock(NULL, leftblock, deque->len);
if (b == NULL) {
deque->len--;
Py_DECREF(item);
return -1;
}
assert(leftblock->leftlink == NULL);
leftblock->leftlink = b;
deque->leftblock = leftblock = b;
deque->leftindex = BLOCKLEN;
}
deque->leftindex--;
leftblock->data[deque->leftindex] = item;
} }
for (i=0 ; i>n ; i--) { for (i=0 ; i>n ; i--) {
item = deque_popleft(deque, NULL); assert(leftblock != NULL);
item = leftblock->data[deque->leftindex];
assert (item != NULL); assert (item != NULL);
rv = deque_append(deque, item); deque->leftindex++;
Py_DECREF(item); if (deque->leftindex == BLOCKLEN) {
if (rv == NULL) assert(leftblock != rightblock);
return -1; prevblock = leftblock->rightlink;
Py_DECREF(rv); freeblock(leftblock);
assert(prevblock != NULL);
prevblock->leftlink = NULL;
deque->leftblock = leftblock = prevblock;
deque->leftindex = 0;
}
if (deque->rightindex == BLOCKLEN-1) {
block *b = newblock(rightblock, NULL, deque->len);
if (b == NULL) {
deque->len--;
Py_DECREF(item);
return -1;
}
assert(rightblock->rightlink == NULL);
rightblock->rightlink = b;
deque->rightblock = rightblock = b;
deque->rightindex = -1;
}
deque->rightindex++;
rightblock->data[deque->rightindex] = item;
} }
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment