[pypy-svn] r49828 - in pypy/branch/gc-prefetch/pypy: config rpython/memory/gc rpython/memory/test

arigo at codespeak.net arigo at codespeak.net
Sun Dec 16 12:28:37 CET 2007


Author: arigo
Date: Sun Dec 16 12:28:35 2007
New Revision: 49828

Added:
   pypy/branch/gc-prefetch/pypy/rpython/memory/gc/prefetchsemispace.py   (contents, props changed)
Modified:
   pypy/branch/gc-prefetch/pypy/config/translationoption.py
   pypy/branch/gc-prefetch/pypy/rpython/memory/gc/base.py
   pypy/branch/gc-prefetch/pypy/rpython/memory/test/test_gc.py
   pypy/branch/gc-prefetch/pypy/rpython/memory/test/test_transformed_gc.py
Log:
Intermediate check-in (still buggy!).


Modified: pypy/branch/gc-prefetch/pypy/config/translationoption.py
==============================================================================
--- pypy/branch/gc-prefetch/pypy/config/translationoption.py	(original)
+++ pypy/branch/gc-prefetch/pypy/config/translationoption.py	Sun Dec 16 12:28:35 2007
@@ -41,7 +41,7 @@
                requires=[("translation.backend", "llvm")]),
     ChoiceOption("gc", "Garbage Collection Strategy",
                  ["boehm", "ref", "marksweep", "semispace", "statistics",
-                  "generation", "none"],
+                  "generation", "prefetch", "none"],
                   "ref", requires={
                      "ref": [("translation.rweakref", False), # XXX
                              ("translation.gctransformer", "ref")],
@@ -51,6 +51,7 @@
                      "marksweep": [("translation.gctransformer", "framework")],
                      "statistics": [("translation.gctransformer", "framework")],
                      "generation": [("translation.gctransformer", "framework")],
+                     "prefetch": [("translation.gctransformer", "framework")],
                      "boehm": [("translation.gctransformer", "boehm")],
                      },
                   cmdline="--gc"),

Modified: pypy/branch/gc-prefetch/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/gc-prefetch/pypy/rpython/memory/gc/base.py	(original)
+++ pypy/branch/gc-prefetch/pypy/rpython/memory/gc/base.py	Sun Dec 16 12:28:35 2007
@@ -265,6 +265,12 @@
         GC_PARAMS = {'space_size': 8*1024*1024} # XXX adjust
         from pypy.rpython.memory.gc.semispace import SemiSpaceGC
         return SemiSpaceGC, GC_PARAMS
+    elif config.translation.gc == "prefetch":
+        GC_PARAMS = {'space_size': 8*1024*1024, # XXX adjust
+                     'prefetch_queue_size': 16} # XXX adjust
+        from pypy.rpython.memory.gc.prefetchsemispace import \
+             PrefetchSemiSpaceGC
+        return PrefetchSemiSpaceGC, GC_PARAMS
     elif config.translation.gc == "generation":
         GC_PARAMS = {'space_size': 8*1024*1024, # XXX adjust
                      'nursery_size': 896*1024}

Added: pypy/branch/gc-prefetch/pypy/rpython/memory/gc/prefetchsemispace.py
==============================================================================
--- (empty file)
+++ pypy/branch/gc-prefetch/pypy/rpython/memory/gc/prefetchsemispace.py	Sun Dec 16 12:28:35 2007
@@ -0,0 +1,90 @@
+from pypy.rpython.memory.gc.semispace import SemiSpaceGC
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi
+from pypy.rpython.extfunc import register_external
+from pypy.rpython.lltypesystem.llmemory import NULL
+
+def prefetch(addr):
+    """This function is used to minimize cache-miss latency by moving
+    data into a cache before it is accessed.  You can insert calls to
+    it into code for which you know addresses of data in memory that
+    is likely to be accessed soon.
+    """
+
+__builtin_prefetch = rffi.llexternal(
+    '__builtin_prefetch',
+    [llmemory.Address, lltype.Signed, lltype.Signed],
+    lltype.Void,
+    sandboxsafe=True, _nowrapper=True)
+
+def llimpl_prefetch(addr):
+    __builtin_prefetch(addr, 0, 0)
+register_external(prefetch, [llmemory.Address], lltype.Void,
+                  'll_hack.builtin_prefetch',
+                  llimpl=llimpl_prefetch,
+                  llfakeimpl=prefetch,
+                  sandboxsafe=True)
+
+# ____________________________________________________________
+
+# The prefetch_queue is a circular first-in first-out buffer.
+# prefetch_queue_next is the index of the next item in prefetch_queue
+# that needs to be removed from the queue, processed, and replaced
+# by the incoming element.  At the beginning, the queue is empty,
+# which we represent by filling it with NULLs.
+
+
+class PrefetchSemiSpaceGC(SemiSpaceGC):
+
+    def __init__(self, *args, **kwds):
+        prefetch_queue_size = kwds.pop('prefetch_queue_size', 4)
+        SemiSpaceGC.__init__(self, *args, **kwds)
+        assert prefetch_queue_size & (prefetch_queue_size-1) == 0, (
+            "prefetch_queue_size must be a power of 2")
+        self.prefetch_queue = lltype.malloc(
+            lltype.FixedSizeArray(llmemory.Address, prefetch_queue_size),
+            immortal=True)
+        self.prefetch_queue_mask = prefetch_queue_size - 1
+
+    def scan_copied(self, scan):
+        # prepare the prefetch queue
+        i = self.prefetch_queue_mask
+        while i >= 0:
+            self.prefetch_queue[i] = NULL
+            i -= 1
+        self.prefetch_queue_next = 0
+        while True:
+            # scan
+            while scan < self.free:
+                curr = scan + self.size_gc_header()
+                self.trace_and_copy_lazy(curr)
+                scan += self.size_gc_header() + self.get_size(curr)
+            # if the prefetch queue is not empty, flush the next item
+            # (note that this is done by "popping" the most recently
+            # added item first, instead of in usual first-in first-out
+            # fashion, so that we know that the queue is completely
+            # empty as soon as we get a NULL)
+            i = self.prefetch_queue_next
+            pointer = self.prefetch_queue[i]
+            if pointer == NULL:
+                break      # empty queue => done
+            self.prefetch_queue[i] = NULL
+            pointer.address[0] = self.copy(pointer.address[0])
+            self.prefetch_queue_next = (i - 1) & self.prefetch_queue_mask
+        return scan
+
+    def trace_and_copy_lazy(self, obj):
+        self.trace(obj, self._trace_copy_lazy, None)
+
+    def _trace_copy_lazy(self, pointer, ignored):
+        if pointer.address[0] != NULL:
+            self.record_pointer_for_tracing(pointer)
+
+    def record_pointer_for_tracing(self, pointer):
+        prefetch(pointer.address[0])
+        i = self.prefetch_queue_next
+        oldpointer = self.prefetch_queue[i]
+        self.prefetch_queue[i] = pointer
+        self.prefetch_queue_next = (i + 1) & self.prefetch_queue_mask
+        if oldpointer != NULL:
+            oldpointer.address[0] = self.copy(oldpointer.address[0])
+    record_pointer_for_tracing.dont_inline = True

Modified: pypy/branch/gc-prefetch/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/branch/gc-prefetch/pypy/rpython/memory/test/test_gc.py	(original)
+++ pypy/branch/gc-prefetch/pypy/rpython/memory/test/test_gc.py	Sun Dec 16 12:28:35 2007
@@ -406,3 +406,7 @@
             return 0
         res = self.interpret(malloc_a_lot, [], backendopt=True, coalloc=True)
         assert res == 0
+
+class TestPrefetchSemiSpaceGC(GCTest):
+    from pypy.rpython.memory.gc.prefetchsemispace import PrefetchSemiSpaceGC
+    GCClass = PrefetchSemiSpaceGC

Modified: pypy/branch/gc-prefetch/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/branch/gc-prefetch/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/branch/gc-prefetch/pypy/rpython/memory/test/test_transformed_gc.py	Sun Dec 16 12:28:35 2007
@@ -896,3 +896,13 @@
         run = self.runner(f, nbargs=0)
         res = run([])
         assert res == 40 * 5
+
+
+class TestPrefetchSemiSpaceGC(GenericMovingGCTests):
+    gcname = "prefetch"
+
+    class gcpolicy(gc.FrameworkGcPolicy):
+        class transformerclass(framework.FrameworkGCTransformer):
+            from pypy.rpython.memory.gc.prefetchsemispace import PrefetchSemiSpaceGC as GCClass
+            GC_PARAMS = {'space_size': 2048, 'prefetch_queue_size': 4}
+            root_stack_depth = 200



More information about the Pypy-commit mailing list