Add implementation notes

This commit is contained in:
Raymond Hettinger 2014-04-23 00:58:48 -07:00
parent b218863012
commit 5402315626
1 changed files with 32 additions and 1 deletions

View File

@ -3,7 +3,7 @@
/* collections module implementation of a deque() datatype /* collections module implementation of a deque() datatype
Written and maintained by Raymond D. Hettinger <python@rcn.com> Written and maintained by Raymond D. Hettinger <python@rcn.com>
Copyright (c) 2004-2013 Python Software Foundation. Copyright (c) 2004-2014 Python Software Foundation.
All rights reserved. All rights reserved.
*/ */
@ -145,6 +145,12 @@ typedef struct {
static PyTypeObject deque_type; static PyTypeObject deque_type;
/* XXX Todo:
If aligned memory allocations become available, make the
deque object 64 byte aligned so that all of the fields
can be retrieved or updated in a single cache line.
*/
static PyObject * static PyObject *
deque_new(PyTypeObject *type, PyObject *args, PyObject *kwds) deque_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{ {
@ -454,6 +460,31 @@ deque_inplace_concat(dequeobject *deque, PyObject *other)
return (PyObject *)deque; return (PyObject *)deque;
} }
/* The rotate() method is part of the public API and is used internally
as a primitive for other methods.
Rotation by 1 or -1 is a common case, so any optimizations for high
volume rotations should take care not to penalize the common case.
Conceptually, a rotate by one is equivalent to a pop on one side and an
append on the other. However, a pop/append pair is unnecessarily slow
because it requires a incref/decref pair for an object located randomly
in memory. It is better to just move the object pointer from one block
to the next without changing the reference count.
When moving batches of pointers, it is tempting to use memcpy() but that
proved to be slower than a simple loop for a variety of reasons.
Memcpy() cannot know in advance that we're copying pointers instead of
bytes, that the source and destination are pointer aligned and
non-overlapping, that moving just one pointer is a common case, that we
never need to move more than BLOCKLEN pointers, and that at least one
pointer is always moved.
For high volume rotations, newblock() and freeblock() are never called
more than once. Previously emptied blocks are immediately reused as a
destination block. If a block is left-over at the end, it is freed.
*/
static int static int
_deque_rotate(dequeobject *deque, Py_ssize_t n) _deque_rotate(dequeobject *deque, Py_ssize_t n)
{ {