Author: Remi Meier <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit