[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