Author: Remi Meier <remi.me...@inf.ethz.ch>
Branch: c8-faster-smallobj-sync
Changeset: r1935:9339deb15d43
Date: 2015-08-11 15:49 +0200
http://bitbucket.org/pypy/stmgc/changeset/9339deb15d43/

Log:    use separate list per size class of obj to increase probability of
        merges

diff --git a/c8/stm/core.c b/c8/stm/core.c
--- a/c8/stm/core.c
+++ b/c8/stm/core.c
@@ -1155,7 +1155,10 @@
 
     assert(list_is_empty(STM_PSEGMENT->modified_old_objects));
     assert(list_is_empty(STM_PSEGMENT->large_overflow_objects));
-    assert(list_is_empty(STM_PSEGMENT->small_overflow_obj_ranges));
+#ifndef NDEBUG
+    for (long i = 2; i < GC_N_SMALL_REQUESTS; i++)
+        assert(list_is_empty(STM_PSEGMENT->small_overflow_obj_ranges[i]));
+#endif
     assert(list_is_empty(STM_PSEGMENT->objects_pointing_to_nursery));
     assert(list_is_empty(STM_PSEGMENT->young_weakrefs));
     assert(tree_is_cleared(STM_PSEGMENT->young_outside_nursery));
@@ -1244,7 +1247,9 @@
     list_clear(STM_PSEGMENT->objects_pointing_to_nursery);
     list_clear(STM_PSEGMENT->old_objects_with_cards_set);
     list_clear(STM_PSEGMENT->large_overflow_objects);
-    list_clear(STM_PSEGMENT->small_overflow_obj_ranges);
+    for (long i = 2; i < GC_N_SMALL_REQUESTS; i++)
+        list_clear(STM_PSEGMENT->small_overflow_obj_ranges[i]);
+
     if (tl != NULL)
         timing_event(tl, event);
 
@@ -1288,18 +1293,20 @@
         release_privatization_lock(STM_SEGMENT->segment_num);
     }
 
-    if (!list_is_empty(STM_PSEGMENT->small_overflow_obj_ranges)) {
-        acquire_privatization_lock(STM_SEGMENT->segment_num);
+    for (long i = 2; i < GC_N_SMALL_REQUESTS; i++) {
+        if (!list_is_empty(STM_PSEGMENT->small_overflow_obj_ranges[i])) {
+            acquire_privatization_lock(STM_SEGMENT->segment_num);
 
-        struct list_s *lst = STM_PSEGMENT->small_overflow_obj_ranges;
-        while (!list_is_empty(lst)) {
-            ssize_t len = (ssize_t)list_pop_item(lst);
-            stm_char *start = (stm_char*)list_pop_item(lst);
-            _synchronize_fragment(start, len);
+            struct list_s *lst = STM_PSEGMENT->small_overflow_obj_ranges[i];
+            while (!list_is_empty(lst)) {
+                ssize_t len = (ssize_t)list_pop_item(lst);
+                stm_char *start = (stm_char*)list_pop_item(lst);
+                _synchronize_fragment(start, len);
+            }
+
+            synchronize_objects_flush();
+            release_privatization_lock(STM_SEGMENT->segment_num);
         }
-
-        synchronize_objects_flush();
-        release_privatization_lock(STM_SEGMENT->segment_num);
     }
 
     /* we can as well clear the list here, since the
@@ -1311,7 +1318,10 @@
        unknown-to-the-segment/uncommitted things.
     */
     list_clear(STM_PSEGMENT->large_overflow_objects);
-    list_clear(STM_PSEGMENT->small_overflow_obj_ranges);
+#ifndef NDEBUG
+    for (long i = 2; i < GC_N_SMALL_REQUESTS; i++)
+        assert(list_is_empty(STM_PSEGMENT->small_overflow_obj_ranges[i]));
+#endif
 }
 
 
@@ -1532,7 +1542,8 @@
     list_clear(pseg->objects_pointing_to_nursery);
     list_clear(pseg->old_objects_with_cards_set);
     list_clear(pseg->large_overflow_objects);
-    list_clear(pseg->small_overflow_obj_ranges);
+    for (long i = 2; i < GC_N_SMALL_REQUESTS; i++)
+        list_clear(pseg->small_overflow_obj_ranges[i]);
     list_clear(pseg->young_weakrefs);
 #pragma pop_macro("STM_SEGMENT")
 #pragma pop_macro("STM_PSEGMENT")
@@ -1811,12 +1822,12 @@
         (struct object_s *)REAL_ADDRESS(STM_SEGMENT->segment_base, obj));
     OPT_ASSERT(obj_size >= 16);
 
-    struct list_s *lst = STM_PSEGMENT->small_overflow_obj_ranges;
+    struct list_s *lst = STM_PSEGMENT->small_overflow_obj_ranges[obj_size / 8];
     if (!list_is_empty(lst)) {
         /* seems to not help to look for merges in this way: */
         stm_char *obj_start = (stm_char*)obj;
         long i;
-        long min = lst->count - 4 * 2; /* go back 4 elems */
+        long min = lst->count - 2 * 2; /* go back 4 elems */
         for (i = lst->count - 2; i >= min; i -= 2) {
             stm_char *start = (stm_char*)lst->items[i];
             ssize_t size = (ssize_t)lst->items[i+1];
@@ -1833,6 +1844,6 @@
     }
 
     /* no merge was found */
-    STM_PSEGMENT->small_overflow_obj_ranges =
+    STM_PSEGMENT->small_overflow_obj_ranges[obj_size / 8] =
         list_append2(lst, (uintptr_t)obj, (uintptr_t)obj_size);
 }
diff --git a/c8/stm/core.h b/c8/stm/core.h
--- a/c8/stm/core.h
+++ b/c8/stm/core.h
@@ -111,11 +111,9 @@
        need to be flushed to other segments on commit (like
        large_overflow_objects). (unsorted, a range never overlaps
        pages) */
-    /* XXX: not much different from before. Maybe try a ranges list
-       per size class. */
     /* XXX: also, we could sweep these ranges on abort and thereby
        free these overflow objs early */
-    struct list_s *small_overflow_obj_ranges;
+    struct list_s *small_overflow_obj_ranges[GC_N_SMALL_REQUESTS];
 
     uint8_t privatization_lock;  // XXX KILL
 
diff --git a/c8/stm/forksupport.c b/c8/stm/forksupport.c
--- a/c8/stm/forksupport.c
+++ b/c8/stm/forksupport.c
@@ -98,7 +98,8 @@
         STM_PSEGMENT->safe_point = SP_NO_TRANSACTION;
         list_clear(STM_PSEGMENT->objects_pointing_to_nursery);
         list_clear(STM_PSEGMENT->large_overflow_objects);
-        list_clear(STM_PSEGMENT->small_overflow_obj_ranges);
+        for (long k = 2; k < GC_N_SMALL_REQUESTS; k++)
+            list_clear(STM_PSEGMENT->small_overflow_obj_ranges[k]);
 
         s_mutex_unlock();
         return;
diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c
--- a/c8/stm/gcpage.c
+++ b/c8/stm/gcpage.c
@@ -599,43 +599,40 @@
 
         /* fix ranges in small_overflow_obj_ranges that may have
            holes from dying objs */
-        lst = pseg->small_overflow_obj_ranges;
-        if (!list_is_empty(lst)) {
-            long j;
-            struct list_s *new_lst = list_create();
-            for (j = lst->count - 2; j >= 0; j -= 2) {
-                stm_char *start = (stm_char*)lst->items[j];
-                ssize_t size = (ssize_t)lst->items[j+1];
+        for (long k = 2; k < GC_N_SMALL_REQUESTS; k++) {
+            lst = pseg->small_overflow_obj_ranges[k];
+            if (!list_is_empty(lst)) {
+                long j;
+                struct list_s *new_lst = list_create();
+                for (j = lst->count - 2; j >= 0; j -= 2) {
+                    stm_char *start = (stm_char*)lst->items[j];
+                    ssize_t size = (ssize_t)lst->items[j+1];
+                    size_t obj_size = k * 8;
 
-                struct object_s *realobj = (struct object_s *)
-                    REAL_ADDRESS(pseg->pub.segment_base, start);
-                size_t obj_size = stmcb_size_rounded_up(realobj);
-                assert(size % obj_size == 0);
-
-                stm_char *obj = start, *range_end = start + size;
-                for (; obj < range_end; obj += obj_size) {
-                    /* note: all these obj-slots *are* in use by overflow objs 
*/
-                    if (!mark_visited_test((object_t*)obj)) {
-                        if (obj != start) {
-                            new_lst = list_append2(new_lst,
-                                                   (uintptr_t)start,
-                                                   (uintptr_t)(obj - start));
+                    stm_char *obj = start, *range_end = start + size;
+                    for (; obj < range_end; obj += obj_size) {
+                        /* note: all these obj-slots *are* in use by overflow 
objs */
+                        if (!mark_visited_test((object_t*)obj)) {
+                            if (obj != start) {
+                                new_lst = list_append2(new_lst,
+                                                       (uintptr_t)start,
+                                                       (uintptr_t)(obj - 
start));
+                            }
+                            start = obj + obj_size; // next start
                         }
-                        start = obj + obj_size; // next start
+                    }
+                    if (obj != start) {
+                        new_lst = list_append2(new_lst,
+                                               (uintptr_t)start,
+                                               (uintptr_t)(obj - start));
                     }
                 }
-                if (obj != start) {
-                    new_lst = list_append2(new_lst,
-                                           (uintptr_t)start,
-                                           (uintptr_t)(obj - start));
-                }
+
+                list_free(lst);
+                pseg->small_overflow_obj_ranges[k] = new_lst;
             }
-
-            list_free(lst);
-            pseg->small_overflow_obj_ranges = new_lst;
         }
 
-
         /* Remove from 'modified_old_objects' all old hashtables that die */
         {
             lst = pseg->modified_old_objects;
diff --git a/c8/stm/setup.c b/c8/stm/setup.c
--- a/c8/stm/setup.c
+++ b/c8/stm/setup.c
@@ -101,7 +101,8 @@
         pr->pub.segment_base = segment_base;
         pr->modified_old_objects = list_create();
         pr->large_overflow_objects = list_create();
-        pr->small_overflow_obj_ranges = list_create();
+        for (long k = 2; k < GC_N_SMALL_REQUESTS; k++)
+            pr->small_overflow_obj_ranges[k] = list_create();
         pr->young_weakrefs = list_create();
         pr->old_weakrefs = list_create();
         pr->objects_pointing_to_nursery = list_create();
@@ -159,9 +160,13 @@
         list_free(pr->old_objects_with_cards_set);
         list_free(pr->modified_old_objects);
         assert(list_is_empty(pr->large_overflow_objects));
-        assert(list_is_empty(pr->small_overflow_obj_ranges));
+#ifndef NDEBUG
+        for (long k = 2; k < GC_N_SMALL_REQUESTS; k++)
+            assert(list_is_empty(pr->small_overflow_obj_ranges[k]));
+#endif
         list_free(pr->large_overflow_objects);
-        list_free(pr->small_overflow_obj_ranges);
+        for (long k = 2; k < GC_N_SMALL_REQUESTS; k++)
+            list_free(pr->small_overflow_obj_ranges[k]);
         list_free(pr->young_weakrefs);
         list_free(pr->old_weakrefs);
         tree_free(pr->young_outside_nursery);
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to