Author: Armin Rigo <[email protected]>
Branch: concurrent-marksweep
Changeset: r48360:230e2318e67c
Date: 2011-10-23 16:19 +0200
http://bitbucket.org/pypy/pypy/changeset/230e2318e67c/

Log:    Only trigger the next minor collection after enough data was
        allocated.

diff --git a/pypy/rpython/memory/gc/concurrentgen.py 
b/pypy/rpython/memory/gc/concurrentgen.py
--- a/pypy/rpython/memory/gc/concurrentgen.py
+++ b/pypy/rpython/memory/gc/concurrentgen.py
@@ -8,6 +8,7 @@
 from pypy.rlib.debug import ll_assert, debug_print, debug_start, debug_stop
 from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, r_uint
 from pypy.rpython.memory.gc.base import GCBase
+from pypy.rpython.memory.gc import env
 from pypy.rpython.memory import gctypelayout
 from pypy.rpython.memory.support import get_address_stack
 from pypy.module.thread import ll_thread
@@ -72,11 +73,25 @@
     # ^^^ prebuilt objects may have the flag FL_WITHHASH;
     #     then they are one word longer, the extra word storing the hash.
 
-    TRANSLATION_PARAMS = {}
+    TRANSLATION_PARAMS = {
+        # Automatically adjust the remaining parameters from the environment.
+        "read_from_env": True,
 
-    def __init__(self, config, **kwds):
+        # The default size of the nursery: use 6 MB by default.
+        # Environment variable: PYPY_GC_NURSERY
+        "nursery_size": 6*1024*1024,
+        }
+
+
+    def __init__(self, config,
+                 read_from_env=False,
+                 nursery_size=16*WORD,
+                 **kwds):
         GCBase.__init__(self, config, **kwds)
-        self.main_thread_ident = ll_thread.get_ident()
+        self.read_from_env = read_from_env
+        self.nursery_size = nursery_size
+        #
+        self.main_thread_ident = ll_thread.get_ident() # non-transl. debug only
         #
         self.extra_objects_to_mark = self.AddressStack()
         self.flagged_objects = self.AddressStack()
@@ -91,6 +106,13 @@
         # is a collection running and the mutator tries to change an object
         # that was not scanned yet.
         self._init_writebarrier_logic()
+        #
+        def trigger_collection_now():
+            # a hack to reduce the code size in _account_for_nursery():
+            # avoids both 'self' and the default argument value to be passed
+            self.trigger_next_collection()
+        trigger_collection_now._dont_inline_ = True
+        self.trigger_collection_now = trigger_collection_now
 
     def _initialize(self):
         # Initialize the GC.  In normal translated program, this function
@@ -134,6 +156,14 @@
         self.acquire(self.ready_to_start_lock)
         #
         self.collector.setup()
+        #
+        self.nursery_size_still_available = r_uint(self.nursery_size)
+        #
+        if self.read_from_env:
+            newsize = env.read_from_env('PYPY_GC_NURSERY')
+            if newsize > 0:
+                self.nursery_size = newsize
+                self.nursery_size_still_available = r_uint(newsize)
 
     def _teardown(self):
         "Stop the collector thread after tests have run."
@@ -162,11 +192,6 @@
     def malloc_fixedsize_clear(self, typeid, size,
                                needs_finalizer=False, contains_weakptr=False):
         #
-        # For now, we always start the next collection as soon as the
-        # previous one is finished
-        if self.collector.running <= 0:
-            self.trigger_next_collection()
-        #
         # Case of finalizers (test constant-folded)
         if needs_finalizer:
             raise NotImplementedError
@@ -182,7 +207,9 @@
         # Regular case
         size_gc_header = self.gcheaderbuilder.size_gc_header
         totalsize = size_gc_header + size
-        adr = llarena.arena_malloc(llmemory.raw_malloc_usage(totalsize), 2)
+        rawtotalsize = llmemory.raw_malloc_usage(totalsize)
+        self._account_for_nursery(rawtotalsize)
+        adr = llarena.arena_malloc(rawtotalsize, 2)
         if adr == llmemory.NULL:
             raise MemoryError
         llarena.arena_reserve(adr, totalsize)
@@ -195,12 +222,6 @@
 
     def malloc_varsize_clear(self, typeid, length, size, itemsize,
                              offset_to_length):
-        #
-        # For now, we always start the next collection as soon as the
-        # previous one is finished
-        if self.collector.running <= 0:
-            self.trigger_next_collection()
-        #
         size_gc_header = self.gcheaderbuilder.size_gc_header
         nonvarsize = size_gc_header + size
         #
@@ -211,7 +232,9 @@
         except OverflowError:
             raise MemoryError
         #
-        adr = llarena.arena_malloc(llmemory.raw_malloc_usage(totalsize), 2)
+        rawtotalsize = llmemory.raw_malloc_usage(totalsize)
+        self._account_for_nursery(rawtotalsize)
+        adr = llarena.arena_malloc(rawtotalsize, 2)
         if adr == llmemory.NULL:
             raise MemoryError
         llarena.arena_reserve(adr, totalsize)
@@ -223,6 +246,13 @@
         self.new_young_objects = hdr
         return llmemory.cast_adr_to_ptr(obj, llmemory.GCREF)
 
+    def _account_for_nursery(self, additional_size):
+        if r_uint(additional_size) > self.nursery_size_still_available:
+            self.trigger_collection_now()
+        else:
+            self.nursery_size_still_available -= additional_size
+    _account_for_nursery._always_inline_ = True
+
     # ----------
     # Other functions in the GC API
 
@@ -470,6 +500,8 @@
         #debug_print("collector.running = 1")
         self.release(self.ready_to_start_lock)
         #
+        self.nursery_size_still_available = r_uint(self.nursery_size)
+        #
         debug_stop("gc-start")
         #
         self.execute_finalizers_ll()
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to