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