Commit Graph

185 Commits

Author SHA1 Message Date
Raymond Hettinger ab517d2eac Fine tune the speed/space trade-off for overallocating small lists.
The Py2.3 approach overallocated small lists by up to 8 elements.
The last checkin would limited this to one but slowed down (by 20 to 30%)
the creation of small lists between 3 to 8 elements.

This tune-up balances the two, limiting overallocation to 3 elements
(significantly reducing space consumption from Py2.3) and running faster
than the previous checkin.

The first part of the growth pattern (0, 4, 8, 16) neatly meshes with
allocators that trigger data movement only when crossing a power of two
boundary.  Also, then even numbers mesh well with common data alignments.
2004-02-14 18:34:46 +00:00
Raymond Hettinger 2731ae4d6d Fix missing return value. Spotted by Neal Norwitz 2004-02-14 03:07:21 +00:00
Raymond Hettinger cb3e580ebc Optimize list.pop() for the common special case of popping off the end.
More than doubles its speed.
2004-02-13 18:36:31 +00:00
Raymond Hettinger 4bb9540dd6 * Optimized list appends and pops by making fewer calls the underlying system
realloc().  This is achieved by tracking the overallocation size in a new
  field and using that information to skip calls to realloc() whenever
  possible.

* Simplified and tightened the amount of overallocation.  For larger lists,
  this overallocates by 1/8th (compared to the previous scheme which ranged
  between 1/4th to 1/32nd over-allocation).  For smaller lists (n<6), the
  maximum overallocation is one byte (formerly it could be upto eight bytes).
  This saves memory in applications with large numbers of small lists.

* Eliminated the NRESIZE macro in favor of a new, static list_resize function
  that encapsulates the resizing logic.  Coverting this back to macro would
  give a small (under 1%) speed-up.  This was too small to warrant the loss
  of readability, maintainability, and de-coupling.

* Some functions using NRESIZE had grown unnecessarily complex in their
  efforts to bend to the macro's calling pattern.  With the new list_resize
  function in place, those other functions could be simplified.  That is
  being saved for a separate patch.

* The ob_item==NULL check could be eliminated from the new list_resize
  function.  This would entail finding each piece of code that sets ob_item
  to NULL and adding a new line to invalidate the overallocation tracking
  field.  Rather than impose a new requirement on other pieces of list code,
  it was preferred to leave the NULL check in place and retain the benefits
  of decoupling, maintainability and information hiding (only PyList_New()
  and list_sort() need to know about the new field).  This approach also
  reduces the odds of breaking an extension module.

(Collaborative effort by Raymond Hettinger, Hye-Shik Chang, Tim Peters,
 and Armin Rigo.)
2004-02-13 11:36:39 +00:00
Tim Peters 7049d816fb Revert change accidentally checked in as part of a whitespace normalization
patch.
2004-01-18 20:31:02 +00:00
Tim Peters 58eb11cf62 Whitespace normalization. 2004-01-18 20:29:55 +00:00
Raymond Hettinger 7832cd6141 Apply tuple/list pre-sizing optimization to a broader class of objects.
Formerly, length data fetched from sequence objects.
Now, any object that reports its length can benefit from pre-sizing.

On one sample timing, it gave a threefold speedup for list(s) where s
was a set object.
2004-01-04 06:08:16 +00:00
Andrew MacIntyre f1ca7f561c complete backout of listobject.c v2.171 2003-12-28 07:43:56 +00:00
Jeremy Hylton 30973414c5 Revert previous two checkins to repair test failure.
The special-case code that was removed could return a value indicating
success but leave an exception set.  test_fileinput failed in a debug
build as a result.
2003-12-26 19:05:04 +00:00
Andrew MacIntyre 694e3a4a9d use the correct macro to access list size 2003-12-26 00:09:04 +00:00
Andrew MacIntyre d57caed52c Performance of list([]) in 2.3 came up in a thread on comp.lang.python,
which can be reviewed via
http://coding.derkeiler.com/Archive/Python/comp.lang.python/2003-12/1011.html

Duncan Booth investigated, and discovered that an "optimisation" was
in fact a pessimisation for small numbers of elements in a source list,
compared to not having the optimisation, although with large numbers
of elements in the source list the optimisation was quite beneficial.

He posted his change to comp.lang.python (but not to SF).

Further research has confirmed his assessment that the optimisation only
becomes a net win when the source list has more than 100 elements.

I also found that the optimisation could apply to tuples as well,
but the gains only arrive with source tuples larger than about 320
elements and are nowhere near as significant as the gains with lists,
(~95% gain @ 10000 elements for lists, ~20% gain @ 10000 elements for
tuples) so I haven't proceeded with this.

The code as it was applied the optimisation to list subclasses as
well, and this also appears to be a net loss for all reasonable sized
sources (~80-100% for up to 100 elements, ~20% for more than 500
elements; I tested up to 10000 elements).

Duncan also suggested special casing empty lists, which I've extended
to all empty sequences.

On the basis that list_fill() is only ever called with a list for the
result argument, testing for the source being the destination has
now happens before testing source types.
2003-12-25 13:28:48 +00:00
Raymond Hettinger 64958a15d7 Guido grants a Christmas wish:
sorted() becomes a regular function instead of a classmethod.
2003-12-17 20:43:33 +00:00
Raymond Hettinger 8f5cdaa784 * Added a new method flag, METH_COEXIST.
* Used the flag to optimize set.__contains__(), dict.__contains__(),
  dict.__getitem__(), and list.__getitem__().
2003-12-13 11:26:12 +00:00
Hye-Shik Chang 19cb193244 Fix memory error treatment correctly. Going to dsu_fail causes
deallocating garbage pointers; saved_ob_item and empty_ob_item.
(Reviewed by Raymond Hettinger)
2003-12-10 07:31:08 +00:00
Michael W. Hudson 1df0f654e8 Fixes and tests for various "holding pointers when arbitrary Python code
can run" bugs as discussed in

[ 848856 ] couple of new list.sort bugs
2003-12-04 11:25:46 +00:00
Raymond Hettinger 37e136373e Make sure the list.sort's decorate step unwinds itself before returning
an exception raised by the key function.
(Suggested by Michael Hudson.)
2003-11-28 21:43:02 +00:00
Raymond Hettinger 001f228f36 Improve the reverse list iterator to free memory as soon as the iterator
is exhausted.
2003-11-08 11:58:44 +00:00
Raymond Hettinger c24c9106e8 Minor code fixup. Make sure that len reflects the current list size. 2003-11-08 11:35:22 +00:00
Raymond Hettinger 1021c44b41 Optimize reversed(list) using a custom iterator. 2003-11-07 15:38:09 +00:00
Jeremy Hylton ceac90aecb Fix compiler warning about possible use of n without assignment.
Also fix use of n for two different variables in two different blocks.
2003-11-03 20:58:28 +00:00
Raymond Hettinger 0a9b9da0c3 Add list.sorted() classmethod. 2003-10-29 06:54:43 +00:00
Raymond Hettinger ae4a299a0d Fix typo found by Neal Norwitz. 2003-10-16 17:16:30 +00:00
Raymond Hettinger 42b1ba31af * list.sort() now supports three keyword arguments: cmp, key, and reverse.
key provides C support for the decorate-sort-undecorate pattern.
  reverse provide a stable sort of the list with the comparisions reversed.

* Amended the docs to guarantee sort stability.
2003-10-16 03:41:09 +00:00
Michael W. Hudson da0a0673b1 My last fix left n used unitialized in tha a==b case.
Fix, by not using n at all in that case.

Needs to be applied to release23-maint, too.
2003-08-15 12:06:41 +00:00
Michael W. Hudson b4f49385a3 Fix reference leak noted in test_types:
Check for a[:] = a _before_ calling PySequence_Fast on a.
release23-maint candidate
Reference leak doesn't happen with head of release22-maint.
2003-08-14 17:04:28 +00:00
Walter Dörwald e8049befdf Use _PyEval_SliceIndex to handle list.index() calls with
huge start and stop arguments. Add tests.
2003-06-17 19:27:39 +00:00
Guido van Rossum 2743d87d79 Fix sloppy index() implementation:
- don't use min() and max()
- interpret negative start/stop argument like negative slice indices
2003-06-17 14:25:14 +00:00
Raymond Hettinger d05abdec7b SF #754014: list.index() should accept optional start, end arguments
Also, modified UserList.index() to match and expanded the related tests.
2003-06-17 05:05:49 +00:00
Raymond Hettinger 6624e68546 SF bug #604716: faster [None]*n or []*n
Fulfilled request to special case repetitions of lists of length 0 or 1.
2003-05-21 05:58:46 +00:00
Raymond Hettinger 686b14d7ad SF bug #730296: Unexpected Changes in list Iterator
Reverted a Py2.3b1 change to iterator in subclasses of list and tuple.
They had been changed to use __getitem__ whenever it had been overriden
in the subclass.

This caused some usabilty and performance problems.  Also, it was
inconsistent with the rest of python where many container methods
access the underlying object directly without first checking for
an overridden getter.  Users needing a change in iterator behavior
should override it directly.
2003-05-07 01:28:47 +00:00
Martin v. Löwis cd12bfc142 Patch #708604: Check more function results. Will backport to 2.2. 2003-05-03 10:53:08 +00:00
Tim Peters 2af713c2f7 Squashed new compiler wngs about trying to compare pointers to
functions with different signatures.
2003-04-24 20:59:52 +00:00
Raymond Hettinger 9928571f3f SF bug 665835: filter() treatment of str and tuple inconsistent
As a side issue on this bug, it was noted that list and tuple iterators
used macros to directly access containers and would not recognize
__getitem__ overrides.  If the method is overridden, the patch returns
a generic sequence iterator which calls the __getitem__ method; otherwise,
it returns a high custom iterator with direct access to container elements.
2003-04-24 16:52:47 +00:00
Guido van Rossum 3a3cca5b82 - list.insert(i, x) now interprets negative i as it would be
interpreted by slicing, so negative values count from the end of the
  list.  This was the only place where such an interpretation was not
  placed on a list index.
2003-04-14 20:58:14 +00:00
Raymond Hettinger 1da1dbf458 Renamed PyObject_GenericGetIter to PyObject_SelfIter
to more accurately describe what the function does.

Suggested by Thomas Wouters.
2003-03-17 19:46:11 +00:00
Raymond Hettinger 0153826964 Created PyObject_GenericGetIter().
Factors out the common case of returning self.
2003-03-17 08:24:35 +00:00
Skip Montanaro 4abd5f0fce Allow list sort's comparison function to explicitly be None. See SF patch
661092.
2003-01-02 20:51:08 +00:00
Raymond Hettinger ea3fdf44a2 SF patch #659536: Use PyArg_UnpackTuple where possible.
Obtain cleaner coding and a system wide
performance boost by using the fast, pre-parsed
PyArg_Unpack function instead of PyArg_ParseTuple
function which is driven by a format string.
2002-12-29 16:33:45 +00:00
Raymond Hettinger f8bcfb13f1 SF Bug 645777: list.extend() works with any iterable and is no longer
experimental.
2002-12-29 05:49:09 +00:00
Michael W. Hudson a69c030c15 The final tweaks before closing
[ 633152 ] list slice ass ignores subtypes of list

Allow arbitrary sequences on the RHS of extended slices.
2002-12-05 21:32:32 +00:00
Tim Peters b9099c3df4 SF patch 637176: list.sort crasher
Armin Rigo's Draconian but effective fix for

SF bug 453523: list.sort crasher

slightly fiddled to catch more cases of list mutation.  The dreaded
internal "immutable list type" is gone!  OTOH, if you look at a list
*while* it's being sorted now, it will appear to be empty.  Better
than a core dump.
2002-11-12 22:08:10 +00:00
Neal Norwitz 03b109afc0 Use PyOS_snprintf() instead of sprintf and wrap the long line 2002-11-05 22:41:37 +00:00
Michael W. Hudson 5da854fe51 This is Alex Martelli's patch
[ 633870 ] allow any seq assignment to a list slice

plus a very silly little test case of my own.
2002-11-05 17:38:05 +00:00
Guido van Rossum bfa5a14adb Darn! Don't divide by zero. Bad fix. :-) 2002-10-11 23:39:35 +00:00
Guido van Rossum a5c0e6d6c8 Add checks for size overflow on list*n, list+list, tuple+tuple.
Will backport.
2002-10-11 21:05:56 +00:00
Neal Norwitz bb9c5f5032 PyObject_RichCompareBool() already returns -1, 0, or 1, so return its value 2002-09-05 21:32:55 +00:00
Raymond Hettinger aae5999b44 Micro-optimization for list_contains. Factored double if test
out of the loop.
2002-09-05 14:23:49 +00:00
Tim Peters e05f65a0c6 1. Combined the base and length arrays into a single array of structs.
This is friendlier for caches.

2. Cut MIN_GALLOP to 7, but added a per-sort min_gallop vrbl that adapts
   the "get into galloping mode" threshold higher when galloping isn't
   paying, and lower when it is.  There's no known case where this hurts.
   It's (of course) neutral for /sort, \sort and =sort.  It also happens
   to be neutral for !sort.  It cuts a tiny # of compares in 3sort and +sort.
   For *sort, it reduces the # of compares to better than what this used to
   do when MIN_GALLOP was hardcoded to 10 (it did about 0.1% more *sort
   compares before, but given how close we are to the limit, this is "a
   lot"!).  %sort used to do about 1.5% more compares, and ~sort about
   3.6% more.  Here are exact counts:

 i    *sort    3sort    +sort    %sort    ~sort    !sort
15   449235    33019    33016    51328   188720    65534  before
     448885    33016    33007    50426   182083    65534  after
      0.08%    0.01%    0.03%    1.79%    3.65%    0.00%  %ch from after

16   963714    65824    65809   103409   377634   131070
     962991    65821    65808   101667   364341   131070
      0.08%    0.00%    0.00%    1.71%    3.65%    0.00%

17  2059092   131413   131362   209130   755476   262142
    2057533   131410   131361   206193   728871   262142
      0.08%    0.00%    0.00%    1.42%    3.65%    0.00%

18  4380687   262440   262460   421998  1511174   524286
    4377402   262437   262459   416347  1457945   524286
      0.08%    0.00%    0.00%    1.36%    3.65%    0.00%

19  9285709   524581   524634   848590  3022584  1048574
    9278734   524580   524633   837947  2916107  1048574
      0.08%    0.00%    0.00%    1.27%    3.65%    0.00%

20 19621118  1048960  1048942  1715806  6045418  2097150
   19606028  1048958  1048941  1694896  5832445  2097150
      0.08%    0.00%    0.00%    1.23%    3.65%    0.00%

3. Added some key asserts I overlooked before.

4. Updated the doc file.
2002-08-10 05:21:15 +00:00
Tim Peters 6063e2615f PyList_Reverse(): This was leaking a reference to Py_None on every call.
I believe I introduced this bug when I refactored the reversal code so
that the mergesort could use it too.  It's not a problem on the 2.2 branch.
2002-08-08 01:06:39 +00:00
Tim Peters 66860f6da4 Sped the usual case for sorting by calling PyObject_RichCompareBool
directly when no comparison function is specified.  This saves a layer
of function call on every compare then.  Measured speedups:

 i    2**i  *sort  \sort  /sort  3sort  +sort  %sort  ~sort  =sort  !sort
15   32768  12.5%   0.0%   0.0% 100.0%   0.0%  50.0% 100.0% 100.0% -50.0%
16   65536   8.7%   0.0%   0.0%   0.0%   0.0%   0.0%  12.5%   0.0%   0.0%
17  131072   8.0%  25.0%   0.0%  25.0%   0.0%  14.3%   5.9%   0.0%   0.0%
18  262144   6.3% -10.0%  12.5%  11.1%   0.0%   6.3%   5.6%  12.5%   0.0%
19  524288   5.3%   5.9%   0.0%   5.6%   0.0%   5.9%   5.4%   0.0%   2.9%
20 1048576   5.3%   2.9%   2.9%   5.1%   2.8%   1.3%   5.9%   2.9%   4.2%

The best indicators are those that take significant time (larger i), and
where sort doesn't do very few compares (so *sort and ~sort benefit most
reliably).  The large numbers are due to roundoff noise combined with
platform variability; e.g., the 14.3% speedup for %sort at i=17 reflects
a printed elapsed time of 0.18 seconds falling to 0.17, but a change in
the last digit isn't really meaningful (indeed, if it really took 0.175
seconds, one electron having a lazy nanosecond could shift it to either
value <wink>).  Similarly the 25% at 3sort i=17 was a meaningless change
from 0.05 to 0.04.  However, almost all the "meaningless changes" were
in the same direction, which is good.  The before-and-after times for
*sort are clearest:

before after
  0.18  0.16
  0.25  0.23
  0.54  0.50
  1.18  1.11
  2.57  2.44
  5.58  5.30
2002-08-04 17:47:26 +00:00