[pypy-commit] stmgc c8-private-pages: fix the slowdown for sort.duh. Still, the real fix would be to avoid adding tons of objs to the modified_old_objects list
Raemi
noreply at buildbot.pypy.org
Tue Jan 20 17:50:43 CET 2015
Author: Remi Meier <remi.meier at inf.ethz.ch>
Branch: c8-private-pages
Changeset: r1560:24ba707614c4
Date: 2015-01-20 17:51 +0100
http://bitbucket.org/pypy/stmgc/changeset/24ba707614c4/
Log: fix the slowdown for sort.duh. Still, the real fix would be to avoid
adding tons of objs to the modified_old_objects list
diff --git a/c7/stm/gcpage.c b/c7/stm/gcpage.c
--- a/c7/stm/gcpage.c
+++ b/c7/stm/gcpage.c
@@ -434,8 +434,8 @@
get_priv_segment(i)->modified_old_objects,
object_t * /*item*/,
({
- mark_visited_test_and_set(item);
- mark_trace(item, stm_object_pages); /* shared version */
+ if (!mark_visited_test_and_set(item))
+ mark_trace(item, stm_object_pages); /* shared version */
mark_trace(item, base); /* private version */
}));
}
diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c
--- a/c8/stm/gcpage.c
+++ b/c8/stm/gcpage.c
@@ -227,14 +227,11 @@
/* trace all references found in sharing seg0 (should always be
up-to-date and not cause segfaults) */
- while (1) {
+ while (!list_is_empty(marked_objects_to_trace)) {
+ obj = (object_t *)list_pop_item(marked_objects_to_trace);
+
realobj = (struct object_s *)REAL_ADDRESS(stm_object_pages, obj);
stmcb_trace(realobj, &mark_record_trace);
-
- if (list_is_empty(marked_objects_to_trace))
- break;
-
- obj = (object_t *)list_pop_item(marked_objects_to_trace);
}
}
@@ -283,23 +280,53 @@
some of the pages) */
long i;
+ struct list_s *uniques = list_create();
for (i = 1; i < NB_SEGMENTS; i++) {
char *base = get_segment_base(i);
+ OPT_ASSERT(list_is_empty(uniques));
+ /* the list of modified_old_objs can be huge and contain a lot
+ of duplicated (same obj, different slice) entries. It seems
+ worth it to build a new list without duplicates.
+ The reason is that newly created objs, when moved out of the
+ nursery, don't have WB_EXECUTED flag. Thus we execute waaay
+ too many write barriers per transaction and add them all
+ to this list (and the commit log). XXXXX */
struct list_s *lst = get_priv_segment(i)->modified_old_objects;
- long j, count = list_count(lst);
- for (j = 0; j < count; j += 3) {
- object_t *item = (object_t*)list_item(lst, j);
- /* All modified objs have all pages accessible for now.
- This is because we create a backup of the whole obj
- and thus make all pages accessible. */
- assert_obj_accessible_in(i, item);
- mark_visited_test_and_set(item);
- mark_and_trace(item, stm_object_pages); /* shared, committed version */
- mark_and_trace(item, base); /* private, modified version */
+ struct stm_undo_s *undo = (struct stm_undo_s *)lst->items;
+ struct stm_undo_s *end = (struct stm_undo_s *)(lst->items + lst->count);
+ for (; undo < end; undo++) {
+ object_t *obj = undo->object;
+ struct object_s *dst = (struct object_s*)REAL_ADDRESS(base, obj);
+
+ if (!(dst->stm_flags & GCFLAG_VISITED)) {
+ LIST_APPEND(uniques, obj);
+ dst->stm_flags |= GCFLAG_VISITED;
+ }
}
+
+
+ LIST_FOREACH_R(uniques, object_t*,
+ ({
+ /* clear the VISITED flags again and actually visit them */
+ struct object_s *dst = (struct object_s*)REAL_ADDRESS(base, item);
+ dst->stm_flags &= ~GCFLAG_VISITED;
+
+ /* All modified objs have all pages accessible for now.
+ This is because we create a backup of the whole obj
+ and thus make all pages accessible. */
+ assert_obj_accessible_in(i, item);
+
+ if (!mark_visited_test_and_set(item))
+ mark_and_trace(item, stm_object_pages); /* shared, committed version */
+ mark_and_trace(item, base); /* private, modified version */
+ }));
+
+
+ list_clear(uniques);
}
+ LIST_FREE(uniques);
}
static void mark_visit_from_roots(void)
More information about the pypy-commit
mailing list