[pypy-commit] stmgc c7: allocate big objects directly outside of the nursery

Remi Meier noreply at buildbot.pypy.org
Thu Jan 30 16:00:03 CET 2014


Author: Remi Meier
Branch: c7
Changeset: r693:5a99e1398932
Date: 2014-01-30 16:00 +0100
http://bitbucket.org/pypy/stmgc/changeset/5a99e1398932/

Log:	allocate big objects directly outside of the nursery

diff --git a/c7/core.h b/c7/core.h
--- a/c7/core.h
+++ b/c7/core.h
@@ -13,6 +13,9 @@
 #define NB_NURSERY_PAGES    1024 // 4MB
 #define LENGTH_SHADOW_STACK   163840
 
+#define NURSERY_SECTION     (32*4096)
+/* (NB_NURSERY_PAGE * 4096) % NURSERY_SECTION == 0 */
+
 
 #define TOTAL_MEMORY          (NB_PAGES * 4096UL * NB_THREADS)
 #define READMARKER_END        ((NB_PAGES * 4096UL) >> 4)
diff --git a/c7/nursery.c b/c7/nursery.c
--- a/c7/nursery.c
+++ b/c7/nursery.c
@@ -193,24 +193,48 @@
 
 object_t *stm_allocate(size_t size)
 {
+    object_t *result;
+    
     _stm_start_safe_point(LOCK_COLLECT);
     /* all collections may happen here */
     _stm_stop_safe_point(LOCK_COLLECT);
     
     assert(_STM_TL->active);
     assert(size % 8 == 0);
-    assert(16 <= size && size < NB_NURSERY_PAGES * 4096);//XXX
+    assert(16 <= size);
 
+    /* XXX move out of fastpath */
+    if (size >= NURSERY_SECTION) {
+        /* allocate large objects outside the nursery immediately,
+           otherwise they may trigger too many minor collections
+           and degrade performance */
+        bool is_small;
+        result = stm_big_small_alloc_old(size, &is_small);
+
+        memset((void*)real_address(result), 0, size);
+
+        /* object is not committed yet */
+        result->stm_flags |= GCFLAG_NOT_COMMITTED;
+        if (is_small)              /* means, not allocated by large-malloc */
+            result->stm_flags |= GCFLAG_SMALL;
+        assert(size == _stm_data_size((struct object_s*)REAL_ADDRESS(get_thread_base(0), result)));
+
+        LIST_APPEND(_STM_TL->uncommitted_objects, result);
+        LIST_APPEND(_STM_TL->old_objects_to_trace, result);
+        return result;
+    }
+    
     localchar_t *current = _STM_TL->nursery_current;
     localchar_t *new_current = current + size;
     _STM_TL->nursery_current = new_current;
     assert((uintptr_t)new_current < (1L << 32));
+
     if ((uintptr_t)new_current > FIRST_AFTER_NURSERY_PAGE * 4096) {
         _STM_TL->nursery_current = current; /* reset for nursery-clearing in minor_collect!! */
         current = collect_and_reserve(size);
     }
 
-    object_t *result = (object_t *)current;
+    result = (object_t *)current;
     return result;
 }
 
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -36,6 +36,9 @@
 typedef ... jmpbufptr_t;
 #define SIZEOF_MYOBJ ...
 
+#define NB_NURSERY_PAGES ...
+#define NURSERY_SECTION ...
+
 void stm_setup(void);
 void stm_setup_thread(void);
 
@@ -244,13 +247,13 @@
 size_t stmcb_size(struct object_s *obj)
 {
     struct myobj_s *myobj = (struct myobj_s*)obj;
-    if (myobj->type_id < 42142) {
+    if (myobj->type_id < 421420) {
         /* basic case: tid equals 42 plus the size of the object */
         assert(myobj->type_id >= 42 + sizeof(struct myobj_s));
         return myobj->type_id - 42;
     }
     else {
-        int nrefs = myobj->type_id - 42142;
+        int nrefs = myobj->type_id - 421420;
         assert(nrefs < 100);
         if (nrefs == 0)   /* weakrefs */
             nrefs = 1;
@@ -262,11 +265,11 @@
 {
     int i;
     struct myobj_s *myobj = (struct myobj_s*)obj;
-    if (myobj->type_id < 42142) {
+    if (myobj->type_id < 421420) {
         /* basic case: no references */
         return;
     }
-    for (i=0; i < myobj->type_id - 42142; i++) {
+    for (i=0; i < myobj->type_id - 421420; i++) {
         object_t **ref = ((object_t **)(myobj + 1)) + i;
         visit(ref);
     }
@@ -308,7 +311,7 @@
 
 def stm_allocate_refs(n):
     o = lib.stm_allocate(HDR + n * WORD)
-    tid = 42142 + n
+    tid = 421420 + n
     lib._set_type_id(o, tid)
     return o
 
diff --git a/c7/test/test_basic.py b/c7/test/test_basic.py
--- a/c7/test/test_basic.py
+++ b/c7/test/test_basic.py
@@ -312,9 +312,8 @@
         assert stm_get_char(lp1) == 'a'
 
     def test_many_allocs(self):
-        # assumes NB_NURSERY_PAGES    1024
         obj_size = 1024
-        num = 9000 # more than what fits in the nursery (4MB)
+        num = (lib.NB_NURSERY_PAGES * 4096) / obj_size + 100 # more than what fits in the nursery
         
         stm_start_transaction()
         for i in range(num):
@@ -333,6 +332,14 @@
         assert old
         assert young
 
+    def test_larger_than_section(self):
+        obj_size = lib.NURSERY_SECTION + 16
+        
+        stm_start_transaction()
+        new = stm_allocate(obj_size)
+        assert not is_in_nursery(new)
+        
+
     def test_large_obj_alloc(self):
         # test obj which doesn't fit into the size_classes
         # for now, we will still allocate it in the nursery.


More information about the pypy-commit mailing list