[pypy-svn] r59257 - pypy/dist/pypy/rpython/memory/gc
fijal at codespeak.net
fijal at codespeak.net
Mon Oct 20 12:55:51 CEST 2008
Author: fijal
Date: Mon Oct 20 12:55:48 2008
New Revision: 59257
Modified:
pypy/dist/pypy/rpython/memory/gc/markcompact.py
Log:
Kill redzone hack. Now we have a proper solution that should shrink number of
allocated pages as object sizes decrease
Modified: pypy/dist/pypy/rpython/memory/gc/markcompact.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc/markcompact.py (original)
+++ pypy/dist/pypy/rpython/memory/gc/markcompact.py Mon Oct 20 12:55:48 2008
@@ -46,6 +46,11 @@
# but compiles to the same pointer. Also we use raw_memmove in case
# objects overlap.
+# Exact algorithm for space resizing: we keep allocated more space than needed
+# (2x, can be even more), but it's full of zeroes. After each collection,
+# we bump next_collect_after which is a marker where to start each collection.
+# It should be exponential (but less than 2) from the size occupied by objects
+
# in case we need to grow space, we use
# current_space_size * FREE_SPACE_MULTIPLIER / FREE_SPACE_DIVIDER + needed
FREE_SPACE_MULTIPLIER = 3
@@ -58,7 +63,7 @@
HDR = lltype.Struct('header', ('tid', lltype.Signed),
('forward_ptr', llmemory.Address))
- TRANSLATION_PARAMS = {'space_size': 2*1024*1024} # XXX adjust
+ TRANSLATION_PARAMS = {'space_size': 8*1024*1024} # XXX adjust
malloc_zero_filled = True
inline_simple_malloc = True
@@ -70,7 +75,7 @@
def __init__(self, config, chunk_size=DEFAULT_CHUNK_SIZE, space_size=4096):
MovingGCBase.__init__(self, config, chunk_size)
self.space_size = space_size
- self.red_zone = 0
+ self.next_collect_after = space_size/2 # whatever...
def setup(self):
if self.config.gcconfig.debugprint:
@@ -78,7 +83,7 @@
self.space = llarena.arena_malloc(self.space_size, True)
ll_assert(bool(self.space), "couldn't allocate arena")
self.free = self.space
- self.top_of_space = self.space + self.space_size
+ self.top_of_space = self.space + self.next_collect_after
MovingGCBase.setup(self)
self.objects_with_finalizers = self.AddressDeque()
self.objects_with_weakrefs = self.AddressStack()
@@ -149,44 +154,41 @@
def try_obtain_free_space(self, needed):
needed = raw_malloc_usage(needed)
- missing = needed - (self.top_of_space - self.free)
- if (self.red_zone >= 2 and self.increase_space_size(needed)):
- return True
- else:
- self.markcompactcollect()
- missing = needed - (self.top_of_space - self.free)
- if missing <= 0:
- return True # success
- else:
- # first check if the object could possibly fit
- if not self.increase_space_size(needed):
- return False
- return True
-
- def new_space_size(self, incr):
- return (self.space_size * FREE_SPACE_MULTIPLIER /
- FREE_SPACE_DIVIDER + incr + FREE_SPACE_ADD)
-
- def increase_space_size(self, needed):
- self.red_zone = 0
- new_size = self.new_space_size(needed)
- newspace = llarena.arena_malloc(new_size, True)
- if not newspace:
- return False
- self.tospace = newspace
- self.space_size = new_size
- self.markcompactcollect(resizing=True)
- return True
+ while 1:
+ self.markcompactcollect(needed)
+ missing = needed - (self.top_of_space - self.free)
+ if missing < 0:
+ return True
+
+ def new_space_size(self, occupied, needed):
+ return (occupied * FREE_SPACE_MULTIPLIER /
+ FREE_SPACE_DIVIDER + FREE_SPACE_ADD + needed)
+
+ def double_space_size(self, minimal_size):
+ while self.space_size <= minimal_size:
+ self.space_size *= 2
+ toaddr = llarena.arena_malloc(self.space_size, True)
+ return toaddr
+
+ def compute_size_of_alive_objects(self):
+ fromaddr = self.space
+ totalsize = 0
+ while fromaddr < self.free:
+ size_gc_header = self.gcheaderbuilder.size_gc_header
+ hdr = llmemory.cast_adr_to_ptr(fromaddr, lltype.Ptr(self.HDR))
+ obj = fromaddr + size_gc_header
+ objsize = self.get_size(obj)
+ objtotalsize = size_gc_header + objsize
+ if self.marked(obj):
+ totalsize += raw_malloc_usage(objtotalsize)
+ fromaddr += objtotalsize
+ return totalsize
def collect(self):
self.markcompactcollect()
- def markcompactcollect(self, resizing=False):
+ def markcompactcollect(self, needed=0):
start_time = self.debug_collect_start()
self.debug_check_consistency()
- if resizing:
- toaddr = self.tospace
- else:
- toaddr = llarena.arena_new_view(self.space)
self.to_see = self.AddressStack()
self.mark_roots_recursively()
if (self.objects_with_finalizers.non_empty() or
@@ -194,6 +196,15 @@
self.mark_objects_with_finalizers()
self._trace_and_mark()
self.to_see.delete()
+ totalsize = self.new_space_size(self.compute_size_of_alive_objects(),
+ needed)
+ if totalsize >= self.space_size:
+ toaddr = self.double_space_size(totalsize)
+ resizing = True
+ else:
+ toaddr = llarena.arena_new_view(self.space)
+ resizing = False
+ self.next_collect_after = totalsize
finaladdr = self.update_forward_pointers(toaddr)
if (self.run_finalizers.non_empty() or
self.objects_with_finalizers.non_empty()):
@@ -212,10 +223,8 @@
llarena.arena_free(self.space)
self.space = toaddr
self.free = finaladdr
- self.top_of_space = toaddr + self.space_size
+ self.top_of_space = toaddr + self.next_collect_after
self.debug_check_consistency()
- if not resizing:
- self.record_red_zone()
if self.run_finalizers.non_empty():
self.execute_finalizers()
self.debug_collect_finish(start_time)
@@ -449,13 +458,3 @@
(obj + offset).address[0] = NULL
self.objects_with_weakrefs.delete()
self.objects_with_weakrefs = new_with_weakref
-
- def record_red_zone(self):
- # XXX KILL ME
- free_after_collection = self.top_of_space - self.free
- if free_after_collection > self.space_size // 3:
- self.red_zone = 0
- else:
- self.red_zone += 1
- if free_after_collection < self.space_size // 5:
- self.red_zone += 1
More information about the Pypy-commit
mailing list