[pypy-commit] stmgc default: Keep track of how much memory we're using

arigo noreply at buildbot.pypy.org
Thu Feb 27 17:34:14 CET 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r894:7bd32f8dc1e8
Date: 2014-02-27 17:34 +0100
http://bitbucket.org/pypy/stmgc/changeset/7bd32f8dc1e8/

Log:	Keep track of how much memory we're using

diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -76,6 +76,7 @@
     char *addr = _stm_large_malloc(size);
     if (addr == NULL)
         stm_fatalerror("not enough memory!\n");
+    increment_total_allocated(size + LARGE_MALLOC_OVERHEAD);
 
     if (addr + size > uninitialized_page_start) {
         uintptr_t npages;
diff --git a/c7/stm/largemalloc.h b/c7/stm/largemalloc.h
--- a/c7/stm/largemalloc.h
+++ b/c7/stm/largemalloc.h
@@ -12,3 +12,6 @@
 void _stm_large_free(char *data);
 
 void _stm_large_dump(void);
+
+
+#define LARGE_MALLOC_OVERHEAD   (2 * sizeof(size_t))   /* estimate */
diff --git a/c7/stm/misc.c b/c7/stm/misc.c
--- a/c7/stm/misc.c
+++ b/c7/stm/misc.c
@@ -71,4 +71,12 @@
     return (object_t *)list_item(
         STM_PSEGMENT->objects_pointing_to_nursery, index);
 }
+
+uint64_t _stm_total_allocated(void)
+{
+    mutex_pages_lock();
+    uint64_t result = increment_total_allocated(0);
+    mutex_pages_unlock();
+    return result;
+}
 #endif
diff --git a/c7/stm/nursery.c b/c7/stm/nursery.c
--- a/c7/stm/nursery.c
+++ b/c7/stm/nursery.c
@@ -213,10 +213,14 @@
         bool locked = false;
         wlog_t *item;
         TREE_LOOP_FORWARD(*STM_PSEGMENT->young_outside_nursery, item) {
+            assert(!_is_in_nursery((object_t *)item->addr));
             if (!locked) {
                 mutex_pages_lock();
                 locked = true;
             }
+            char *realobj = REAL_ADDRESS(STM_SEGMENT->segment_base,item->addr);
+            ssize_t size = stmcb_size_rounded_up((struct object_s *)realobj);
+            increment_total_allocated(-(size + LARGE_MALLOC_OVERHEAD));
             _stm_large_free(stm_object_pages + item->addr);
         } TREE_LOOP_END;
 
diff --git a/c7/stm/pages.c b/c7/stm/pages.c
--- a/c7/stm/pages.c
+++ b/c7/stm/pages.c
@@ -6,10 +6,19 @@
 /************************************************************/
 
 static union {
-    uint8_t mutex_pages;
+    struct {
+        uint8_t mutex_pages;
+        uint64_t total_allocated;  /* keep track of how much memory we're
+                                      using, ignoring nurseries */
+    };
     char reserved[64];
 } pages_ctl __attribute__((aligned(64)));
 
+static void teardown_pages(void)
+{
+    memset(&pages_ctl, 0, sizeof(pages_ctl));
+}
+
 static void mutex_pages_lock(void)
 {
     while (__sync_lock_test_and_set(&pages_ctl.mutex_pages, 1) != 0) {
@@ -28,6 +37,13 @@
     return pages_ctl.mutex_pages != 0;
 }
 
+static uint64_t increment_total_allocated(ssize_t add_or_remove)
+{
+    assert(_has_mutex_pages());
+    pages_ctl.total_allocated += add_or_remove;
+    return pages_ctl.total_allocated;
+}
+
 /************************************************************/
 
 
@@ -108,6 +124,7 @@
     }
     write_fence();
     memset(flag_page_private + pagenum, PRIVATE_PAGE, count);
+    increment_total_allocated(4096 * count);
 }
 
 static void _pages_privatize(uintptr_t pagenum, uintptr_t count, bool full)
diff --git a/c7/stm/pages.h b/c7/stm/pages.h
--- a/c7/stm/pages.h
+++ b/c7/stm/pages.h
@@ -23,6 +23,7 @@
 
 static void mutex_pages_lock(void);
 static void mutex_pages_unlock(void);
+static uint64_t increment_total_allocated(ssize_t add_or_remove);
 
 inline static void pages_privatize(uintptr_t pagenum, uintptr_t count,
                                    bool full) {
diff --git a/c7/stm/setup.c b/c7/stm/setup.c
--- a/c7/stm/setup.c
+++ b/c7/stm/setup.c
@@ -101,6 +101,7 @@
     teardown_sync();
     teardown_gcpage();
     teardown_nursery();
+    teardown_pages();
 }
 
 void _init_shadow_stack(stm_thread_local_t *tl)
diff --git a/c7/stmgc.h b/c7/stmgc.h
--- a/c7/stmgc.h
+++ b/c7/stmgc.h
@@ -92,6 +92,7 @@
 long _stm_count_objects_pointing_to_nursery(void);
 object_t *_stm_enum_modified_old_objects(long index);
 object_t *_stm_enum_objects_pointing_to_nursery(long index);
+uint64_t _stm_total_allocated(void);
 #endif
 
 #define _STM_GCFLAG_WRITE_BARRIER      0x01
diff --git a/c7/test/support.py b/c7/test/support.py
--- a/c7/test/support.py
+++ b/c7/test/support.py
@@ -70,6 +70,7 @@
 object_t *_stm_enum_objects_pointing_to_nursery(long index);
 
 void stm_collect(long level);
+uint64_t _stm_total_allocated(void);
 """)
 
 
@@ -215,7 +216,7 @@
     }
     else {
         int nrefs = myobj->type_id - 421420;
-        assert(nrefs < 100);
+        assert(nrefs < 10000);     /* artificial limit, to check for garbage */
         if (nrefs == 0)   /* weakrefs */
             nrefs = 1;
         return sizeof(struct myobj_s) + nrefs * sizeof(void*);
diff --git a/c7/test/test_nursery.py b/c7/test/test_nursery.py
--- a/c7/test/test_nursery.py
+++ b/c7/test/test_nursery.py
@@ -85,13 +85,17 @@
         obj_size = lib._STM_FAST_ALLOC + 16
 
         self.start_transaction()
+        assert lib._stm_total_allocated() == 0
         seen = set()
         for i in range(10):
             stm_minor_collect()
             new = stm_allocate(obj_size)
             assert not is_in_nursery(new)
+            assert lib._stm_total_allocated() == obj_size + 16
             seen.add(new)
         assert len(seen) < 5     # addresses are reused
+        stm_minor_collect()
+        assert lib._stm_total_allocated() == 0
 
     def test_larger_than_limit_for_nursery_dont_die(self):
         obj_nrefs = (lib._STM_FAST_ALLOC + 16) // 8
@@ -115,6 +119,19 @@
             lp1 = stm_get_ref(lp1, i)
         assert not lp1
 
+    def test_account_for_privatized_page(self):
+        self.start_transaction()
+        obj = stm_allocate(16)
+        self.push_root(obj)
+        self.commit_transaction()
+        obj = self.pop_root()
+        base = lib._stm_total_allocated()
+        assert base <= 4096
+
+        self.start_transaction()
+        stm_write(obj)
+        assert lib._stm_total_allocated() == base + 4096
+
     def test_reset_partial_alloc_pages(self):
         py.test.skip("a would-be-nice feature, but not actually needed: "
                      "the next major GC will take care of it")


More information about the pypy-commit mailing list