[pypy-commit] stmgc card-marking: optimize a bit the card-wise synchronize objs

Raemi noreply at buildbot.pypy.org
Thu May 22 16:58:53 CEST 2014


Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: card-marking
Changeset: r1231:8fac7b4ff774
Date: 2014-05-22 13:45 +0200
http://bitbucket.org/pypy/stmgc/changeset/8fac7b4ff774/

Log:	optimize a bit the card-wise synchronize objs

diff --git a/c7/stm/core.c b/c7/stm/core.c
--- a/c7/stm/core.c
+++ b/c7/stm/core.c
@@ -516,7 +516,7 @@
     long i, myself = STM_SEGMENT->segment_num;
 
     /* simple heuristic to check if probably the whole object is
-       marked anyway so we can do page-wise synchronize */
+       marked anyway so we should do page-wise synchronize */
     if (write_locks[first_card_index + 1] == CARD_MARKED_OLD
         && write_locks[first_card_index + last_card_index] == CARD_MARKED_OLD
         && write_locks[first_card_index + (last_card_index >> 1) + 1] == CARD_MARKED_OLD) {
@@ -530,20 +530,38 @@
 
     dprintf(("card_wise_sync syncs %p,size:%lu card-wise\n", obj, obj_size));
 
+    /* Combine multiple marked cards and do a memcpy for them. We don't
+       try yet to use page_copy() or otherwise take into account privatization
+       of pages (except _has_private_page_in_range) */
+    uintptr_t start = 0;
+    uintptr_t copy_size = 0;
     while (card_index <= last_card_index) {
         uintptr_t card_lock_idx = first_card_index + card_index;
+        uintptr_t card_byte_offset = get_card_byte_offset(card_index);
+        uint8_t card_value = write_locks[card_lock_idx];
 
-        if (write_locks[card_lock_idx] == CARD_MARKED_OLD) {
+        OPT_ASSERT(card_value != CARD_MARKED); /* always only MARKED_OLD or CLEAR */
+
+        if (card_value == CARD_MARKED_OLD) {
             write_locks[card_lock_idx] = CARD_CLEAR;
 
-            uintptr_t card_byte_offset = get_card_byte_offset(card_index);
-            uintptr_t start = (uintptr_t)obj + card_byte_offset;
-            uintptr_t copy_size = CARD_SIZE;
+            if (start == 0) {   /* first marked card */
+                start = (uintptr_t)obj + card_byte_offset;
+            }
 
-            if (start - (uintptr_t)obj + copy_size > obj_size) {
+            copy_size += CARD_SIZE;
+
+            if ((start - (uintptr_t)obj) + copy_size > obj_size) {
                 /* don't copy over the object's bounds */
                 copy_size = obj_size - (start - (uintptr_t)obj);
             }
+        }
+
+        if (start                                     /* something to copy */
+            && (card_value != CARD_MARKED_OLD         /* found non-marked card */
+                || card_index == last_card_index)) {  /* this is the last card */
+            /* do the copying: */
+            //dprintf(("copy %lu bytes\n", copy_size));
 
             /* since we have marked cards, at least one page here must be private */
             assert(_has_private_page_in_range(myself, start, copy_size));
@@ -553,6 +571,7 @@
             char *dst = REAL_ADDRESS(stm_object_pages, start);
             memcpy(dst, src, copy_size);
 
+            /* copy to other segments */
             for (i = 1; i <= NB_SEGMENTS; i++) {
                 if (i == myself)
                     continue;
@@ -562,12 +581,22 @@
                 dst = REAL_ADDRESS(get_segment_base(i), start);
                 memcpy(dst, src, copy_size);
             }
-        } else {
-            assert(write_locks[card_lock_idx] != CARD_MARKED); /* always only MARKED_OLD */
+
+            copy_size = 0;
+            start = 0;
         }
 
         card_index++;
     }
+
+#ifndef NDEBUG
+    char *src = REAL_ADDRESS(stm_object_pages, (uintptr_t)obj);
+    char *dst;
+    for (i = 1; i <= NB_SEGMENTS; i++) {
+        dst = REAL_ADDRESS(get_segment_base(i), (uintptr_t)obj);
+        assert(memcmp(dst, src, obj_size) == 0);
+    }
+#endif
 }
 
 
diff --git a/c7/test/test_card_marking.py b/c7/test/test_card_marking.py
--- a/c7/test/test_card_marking.py
+++ b/c7/test/test_card_marking.py
@@ -186,3 +186,46 @@
         assert not stm_was_written_card(o)
         assert stm_get_ref(o, 0) == p
         self.commit_transaction()
+
+    def test_synchronize_objs(self):
+        o = stm_allocate_old(2000, True)
+
+        self.start_transaction()
+        stm_set_char(o, 'a', 1000, False)
+        self.commit_transaction()
+
+        self.switch(1)
+
+        self.start_transaction()
+        stm_set_char(o, 'b', 1001, False)
+        assert stm_get_char(o, 1000) == 'a'
+        self.commit_transaction()
+
+        self.switch(0)
+
+        self.start_transaction()
+        assert stm_get_char(o, 1001) == 'b'
+
+        stm_set_char(o, 'c', 1000, True)
+        stm_set_char(o, 'c', 1000+CARD_SIZE, True)
+        stm_set_char(o, 'c', 1000+CARD_SIZE*2, True)
+        stm_set_char(o, 'c', 1000+CARD_SIZE*3, True)
+
+        stm_set_char(o, 'd', 1000+CARD_SIZE*10, True)
+
+        stm_set_char(o, 'e', 1000+CARD_SIZE*12, True)
+        self.commit_transaction()
+
+        self.switch(1)
+
+        self.start_transaction()
+        assert stm_get_char(o, 1000) == 'c'
+        assert stm_get_char(o, 1000+CARD_SIZE) == 'c'
+        assert stm_get_char(o, 1000+CARD_SIZE*2) == 'c'
+        assert stm_get_char(o, 1000+CARD_SIZE*3) == 'c'
+
+        assert stm_get_char(o, 1000+CARD_SIZE*10) == 'd'
+
+        assert stm_get_char(o, 1000+CARD_SIZE*12) == 'e'
+
+        self.commit_transaction()


More information about the pypy-commit mailing list