[pypy-commit] pypy stm-gc: Remove the global lock during the commit_transaction() at the GC level.
arigo
noreply at buildbot.pypy.org
Mon Feb 20 15:32:42 CET 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: stm-gc
Changeset: r52678:fd93fb6a06eb
Date: 2012-02-20 15:32 +0100
http://bitbucket.org/pypy/pypy/changeset/fd93fb6a06eb/
Log: Remove the global lock during the commit_transaction() at the GC
level.
diff --git a/pypy/rpython/memory/gc/stmgc.py b/pypy/rpython/memory/gc/stmgc.py
--- a/pypy/rpython/memory/gc/stmgc.py
+++ b/pypy/rpython/memory/gc/stmgc.py
@@ -50,15 +50,18 @@
('malloc_flags', lltype.Signed),
('pending_list', llmemory.Address),
('surviving_weakrefs', llmemory.Address),
+ ('global_free', llmemory.Address),
+ ('global_stop', llmemory.Address),
)
TRANSLATION_PARAMS = {
'stm_operations': 'use_real_one',
'max_nursery_size': 400*1024*1024, # XXX 400MB
+ 'tls_page_size': 64*1024, # 64KB
}
def __init__(self, config, stm_operations='use_emulator',
- max_nursery_size=1024,
+ max_nursery_size=1024, tls_page_size=64,
**kwds):
GCBase.__init__(self, config, **kwds)
#
@@ -72,6 +75,7 @@
self.stm_operations = stm_operations
self.collector = Collector(self)
self.max_nursery_size = max_nursery_size
+ self.tls_page_size = tls_page_size
#
def _get_size(obj): # indirection to hide 'self'
return self.get_size(obj)
@@ -101,7 +105,7 @@
def setup_thread(self, in_main_thread):
"""Setup a thread. Allocates the thread-local data structures.
Must be called only once per OS-level thread."""
- tls = lltype.malloc(self.GCTLS, flavor='raw')
+ tls = lltype.malloc(self.GCTLS, zero=True, flavor='raw')
self.stm_operations.set_tls(llmemory.cast_ptr_to_adr(tls),
int(in_main_thread))
tls.nursery_start = self._alloc_nursery()
@@ -217,6 +221,34 @@
return obj
+ def _malloc_global_raw(self, tls, size):
+ # For collection: allocates enough space for a global object from
+ # the main_tls. The argument 'tls' is the current (local) GCTLS.
+ # We try to do it by reserving "pages" of memory from the global
+ # area at once, and subdividing here.
+ size_gc_header = self.gcheaderbuilder.size_gc_header
+ totalsize = size_gc_header + size
+ freespace = tls.global_stop - tls.global_free
+ if freespace < llmemory.raw_malloc_usage(totalsize):
+ self._malloc_global_more(tls, llmemory.raw_malloc_usage(totalsize))
+ result = tls.global_free
+ tls.global_free = result + totalsize
+ llarena.arena_reserve(result, totalsize)
+ obj = result + size_gc_header
+ return obj
+
+ @dont_inline
+ def _malloc_global_more(self, tls, totalsize):
+ if totalsize < self.tls_page_size:
+ totalsize = self.tls_page_size
+ main_tls = self.main_thread_tls
+ self.acquire(self.mutex_lock)
+ result = self._allocate_bump_pointer(main_tls, totalsize)
+ self.release(self.mutex_lock)
+ tls.global_free = result
+ tls.global_stop = result + totalsize
+
+
def collect(self, gen=0):
raise NotImplementedError
@@ -376,11 +408,9 @@
# We need to allocate a global object here. We only allocate
# it for now; it is left completely uninitialized.
size = self.get_size(obj)
- self.acquire(self.mutex_lock)
- main_tls = self.main_thread_tls
- globalobj = self._malloc_local_raw(main_tls, size)
+ tls = self.collector.get_tls()
+ globalobj = self._malloc_global_raw(tls, size)
self.header(globalobj).tid = GCFLAG_GLOBAL
- self.release(self.mutex_lock)
#
# Update the header of the local 'obj'
hdr.tid |= GCFLAG_HAS_SHADOW
@@ -463,9 +493,7 @@
#
# Do a mark-and-move minor collection out of the tls' nursery
# into the main thread's global area (which is right now also
- # called a nursery). To simplify things, we use a global lock
- # around the whole mark-and-move.
- self.gc.acquire(self.gc.mutex_lock)
+ # called a nursery).
debug_print("local arena:", tls.nursery_free - tls.nursery_start,
"bytes")
#
@@ -481,8 +509,6 @@
# local objects
self.collect_from_pending_list(tls)
#
- self.gc.release(self.gc.mutex_lock)
- #
# Fix up the weakrefs that used to point to local objects
self.fixup_weakrefs(tls)
#
@@ -572,8 +598,7 @@
# First visit to a local-only 'obj': allocate a corresponding
# global object
size = self.gc.get_size(obj)
- main_tls = self.gc.main_thread_tls
- globalobj = self.gc._malloc_local_raw(main_tls, size)
+ globalobj = self.gc._malloc_global_raw(tls, size)
need_to_copy = True
#
else:
diff --git a/pypy/rpython/memory/gc/test/test_stmgc.py b/pypy/rpython/memory/gc/test/test_stmgc.py
--- a/pypy/rpython/memory/gc/test/test_stmgc.py
+++ b/pypy/rpython/memory/gc/test/test_stmgc.py
@@ -340,7 +340,9 @@
assert s.b == 12345 # not updated by the GC code
assert t.b == 67890 # still valid
- def test_commit_transaction_with_one_reference(self):
+ def _commit_transaction_with_one_reference(self, tls_page_size):
+ self.gc.tls_page_size = tls_page_size
+ #
sr, sr_adr = self.malloc(SR)
assert sr.s1 == lltype.nullptr(S)
assert sr.sr2 == lltype.nullptr(SR)
@@ -359,9 +361,23 @@
#
self.gc.collector.commit_transaction()
#
- assert main_tls.nursery_free - old_value == self.gcsize(S)
+ consumed = main_tls.nursery_free - old_value
+ expected = self.gcsize(S) # round this value up to tls_page_size
+ if expected < tls_page_size: expected = tls_page_size
+ assert consumed == expected
+
+ def test_commit_transaction_with_one_reference_1(self):
+ self._commit_transaction_with_one_reference(1)
+
+ def test_commit_transaction_with_one_reference_N1(self):
+ N1 = self.gcsize(S)-1
+ self._commit_transaction_with_one_reference(N1)
+
+ def test_commit_transaction_with_one_reference_128(self):
+ self._commit_transaction_with_one_reference(128)
def test_commit_transaction_with_graph(self):
+ self.gc.tls_page_size = 1
sr1, sr1_adr = self.malloc(SR)
sr2, sr2_adr = self.malloc(SR)
self.select_thread(1)
More information about the pypy-commit
mailing list