Python vs Ruby

hansboehm at my-deja.com hansboehm at my-deja.com
Wed Jan 31 13:53:24 EST 2001


In article <mailman.980835459.24363.python-list at python.org>,
  "Tim Peters" <tim.one at home.com> wrote:
> [Neil Schemenauer]
> > RC also works quite well with data caches and VM managers.  Using
> > the Boehm-Demers GC with Python and disabling reference counting
> > slows the interpreter down by a significant amount.
>
Are you sure the collector is working correctly, and not retaining
garbage for some reason?  I looked at the source tree quickly, and it
appeared to me that the interpreter maintained a doubly linked list of
all Python objects?  That would effectively keep the collector from
reclaiming anything.  Is that list essential?

When I last looked at this 4 or 5 years ago, there were some other
issues that prevented a direct plug-in of a tracing collector.  I think
some subsystems did their own free-list management.  This tends to be a
pessimization with a tracing GC, especially if the objects on the free
list still point to other long-dead objects, etc.  I couldn't find such
issues now, but I didn't look very hard.

You can probably get a good idea whether any of these are an issue by
building the collector without -DSILENT, and looking at the amount of
reachable memory it found.
...

> Thanks to refcounting, the storage for "s" is reclaimed on each
iteration,
> and overwhelmingly most iterations manage to reuse the storage left
behind
> from a preceding iteration.  As Neil said, that's very cache-friendly.
> Without refcounting, you're likely to stomp on new memory addresses
each
> iteration until some limit is reached, then gc will go lurching all
over a
> large blob of memory at least once (possibly more) cleaning it up.
That's
> cache-hostile.
True, although there are some tricks you can play to reduce the effect.
See http://www.hpl.hp.com/techreports/2000/HPL-2000-99.html (also in the
ISMM 2000 Proceedings).  Much of the remaining cost is that with
reference counting (or malloc/free style memory management) you often
get to allocate memory that's already in the cache.  With a M/S GC, you
usually don't.

On the other hand, reference counting is also rather cache-unfriendly,
in a different way. Assigning a reference now needs to touch both the
previously referenced and the newly referenced object, which are very
unlikely to be on the same cache line.  And both lines are dirtied, so
they will need to be written back when they are replaced.

Reference counting tends to look considerably worse if you fully support
concurrency, so that you have to update reference counts with atomic
operations.  But in my experience it rarely wins for small objects even
in the single-threaded case.  (It can win for large objects, or if you
are very tight on space, so that you would have to collect too often.)
>
> Python has extremely high dynamic memory throughput, because *nothing*
is
> exempted from the "everything's an object, and all objects are
> heap-allocated" scheme.  Mark-&-sweep-- and especially simple M&S --is
> happier with modest rates of memory turnover.
I agree that reference counting looks relatively better with a high
allocation to pointer assignment ratio.  But I would also claim that
there are some high allocation rate programs for which mark/sweep is
clearly the winning strategy, e.g. if you repeatedly build a large data
structure, traverse/tweak it a few times, and then drop it.  If you
mostly allocate very short-lived objects, copying generational
collectors are hard to beat.
...

Hans

Hans_Boehm<at>hp<dot>com


Sent via Deja.com
http://www.deja.com/



More information about the Python-list mailing list