Skip to content

Apply freelist technique to empty lists #40215

Closed

Description

@rhettinger
BPO 947476
Nosy @tim-one, @arigo, @rhettinger
Files
  • listobject2.diff: Revised patch (gets all PyListObject blocks)
  • listobject3.diff: Revised to include Tim's and Armin's suggestions
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/rhettinger'
    closed_at = <Date 2004-05-05.05:38:56.000>
    created_at = <Date 2004-05-04.05:47:14.000>
    labels = ['interpreter-core']
    title = 'Apply freelist technique to empty lists'
    updated_at = <Date 2004-05-05.05:38:56.000>
    user = 'https://github.com/rhettinger'

    bugs.python.org fields:

    activity = <Date 2004-05-05.05:38:56.000>
    actor = 'rhettinger'
    assignee = 'rhettinger'
    closed = True
    closed_date = None
    closer = None
    components = ['Interpreter Core']
    creation = <Date 2004-05-04.05:47:14.000>
    creator = 'rhettinger'
    dependencies = []
    files = ['5962', '5963']
    hgrepos = []
    issue_num = 947476
    keywords = ['patch']
    message_count = 13.0
    messages = ['45940', '45941', '45942', '45943', '45944', '45945', '45946', '45947', '45948', '45949', '45950', '45951', '45952']
    nosy_count = 3.0
    nosy_names = ['tim.peters', 'arigo', 'rhettinger']
    pr_nums = []
    priority = 'normal'
    resolution = 'accepted'
    stage = None
    status = 'closed'
    superseder = None
    type = None
    url = 'https://bugs.python.org/issue947476'
    versions = ['Python 2.4']

    Activity

    1. rhettinger commented on May 4, 2004

      @rhettinger
      ContributorAuthor

      Saves malloc/free and reduces fragmentation for the
      ubiquitous operation of instantiating and freeing empty
      lists.

      Improves the timing of timeit.py "[]" by about a quarter.

    2. self-assigned this
      on May 4, 2004
    3. self-assigned this
      on May 4, 2004
    4. arigo commented on May 4, 2004

      arigomannequin
      Mannequin

      Logged In: YES
      user_id=4771

      Why is the idea restricted to empty lists? A priori I don't
      see why empty lists are so common. On the other hand we
      should be able to save and restore the PyListObject part of
      any list using the same mecanism.

    5. rhettinger commented on May 4, 2004

      @rhettinger
      ContributorAuthor

      Logged In: YES
      user_id=80475

      Attaching a revised patch that incorporates your suggestion
      about always being able to save/restore the PyListObject part.

      The a priori reason empty lists are so common is that most
      lists are built up from zero. Also, there is a lot a
      testing for a==[] and default instantiation in expressions
      like mydict.setdefault(k, []).append(v).

      A posteriori, it is easy to get a quick visual on the this,
      add a printf("*") on one side of the "if" and printf(".") on
      the other. Then run the test suite. The pattern of
      PyList_New(0) calls completely dominate the output. It
      looks like about 90% of the PyList_New calls are for size 0
      (this pattern holds is not unique -- it holds across the
      whole test suite).

      The patch captures the benefit for the most common cases and
      avoids the code complexity and overhead of tracking multiple
      blocks of different sized memory blocks (that is what
      PyMalloc is supposed to be good at).

    6. arigo commented on May 4, 2004

      arigomannequin
      Mannequin

      Logged In: YES
      user_id=4771

      Ok. I meant that lists that are still empty when they are
      destructed are probably not too common, although most lists
      are created empty.

    7. tim-one commented on May 4, 2004

      @tim-one
      Member

      Logged In: YES
      user_id=31435

      FWIW, I like this. The list header could also be reclaimed
      from the freelist regardless of list size, a la

      if (free list isn't empty) {
          op = pop off the free list;
          do object initialization;
          if (size == 0) {
              finish & return;
          }
      else {
          op = PyObject_GC_New(...);
          if (op == NULL) error;
      }

      Note that PyMalloc isn't involved in allocating list *guts*
      regardless of list size. They're allocated with
      PyMem_MALLOC, which is the system malloc(). That's a
      murkier tradoff (if the guts get "too big" for PyMalloc later,
      the PyMalloc realloc function is a bit slower than calling the
      system realloc, since the former has the additional overhead
      of deducing that it needs to call the latter; OTOH, we no
      longer call a realloc function on every stinkin' append
      anymore).

    8. rhettinger commented on May 4, 2004

      @rhettinger
      ContributorAuthor

      Logged In: YES
      user_id=80475

      Okay, I see. If that was an issue, it was fixed by
      incorporating your suggestion which means that the freelist
      will almost never be starved.

    9. arigo commented on May 4, 2004

      arigomannequin
      Mannequin

      Logged In: YES
      user_id=4771

      Wouldn't it be nice to have a set of macros for free lists,
      something that could easily be dropped in any object
      implementation and that would do the right thing, e.g. cache
      the ob_type?

      When looking at integers, I can't help noticing that they
      reinitialize the ob_type field at each object creation.
      Would it pay to try to remove that?

    10. rhettinger commented on May 4, 2004

      @rhettinger
      ContributorAuthor

      Logged In: YES
      user_id=80475

      The needs of the different types vary enough to make a
      single macro set unlikely. Also, macros tend to hide what
      is going on under the hood making it difficult to discern
      genuine optimizations.

      Sound like there may be room for improvement for integers.
      Sticking with small steps though, I'll take lists today and
      leave integers for another patch on another day.

    11. tim-one commented on May 4, 2004

      @tim-one
      Member

      Logged In: YES
      user_id=31435

      WRT ints, the free list is chained together via abusing the
      ob_type field, and there's no other field in a PyIntObject
      guaranteed large enough to hold a pointer (or guaranteed to
      be pointer-aligned).

    12. rhettinger commented on May 4, 2004

      @rhettinger
      ContributorAuthor

      Logged In: YES
      user_id=80475

      Attaching a new patch that incorporates both Tim and Armin's
      suggestions. The PyListObject portion is always reclaimed
      whenever there is room in the free list. The header is
      always re-used when available. This provides some benefit
      to lists of all sizes and it simplifies the patch a bit.

    13. rhettinger commented on May 5, 2004

      @rhettinger
      ContributorAuthor

      Logged In: YES
      user_id=80475

      Any further ideas or should I go ahead and put this one in?

    14. tim-one commented on May 5, 2004

      @tim-one
      Member

      Logged In: YES
      user_id=31435

      Marked Accepted & assigned back to you. If Armin wants
      more changes, he (or you, or I, or ...) can fiddle it later.
      What's here is fine!

    15. rhettinger commented on May 5, 2004

      @rhettinger
      ContributorAuthor

      Logged In: YES
      user_id=80475

      Thanks. Checked-in as Objects/llistobject.c 2.204

    16. transferred this issue fromon Apr 9, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions