Author: Tobias Weber <tobias_webe...@gmx.de> Branch: c8-adaptive-trx-length Changeset: r2043:efebf97ce6b2 Date: 2017-04-26 21:11 +0200 http://bitbucket.org/pypy/stmgc/changeset/efebf97ce6b2/
Log: Merge overheads instrumentation diff --git a/c8/stm/core.c b/c8/stm/core.c --- a/c8/stm/core.c +++ b/c8/stm/core.c @@ -158,6 +158,9 @@ { /* returns true if we reached a valid state, or false if we need to abort now */ + start_timer(); + stm_thread_local_t *thread_local_for_logging = STM_SEGMENT->running_thread; + dprintf(("_stm_validate() at cl=%p, rev=%lu\n", STM_PSEGMENT->last_commit_log_entry, STM_PSEGMENT->last_commit_log_entry->rev_num)); /* go from last known entry in commit log to the @@ -171,6 +174,11 @@ if (STM_PSEGMENT->transaction_state == TS_INEVITABLE) { assert(first_cl->next == INEV_RUNNING); + + if (thread_local_for_logging != NULL) { + stop_timer_and_publish_for_thread( + thread_local_for_logging, STM_DURATION_VALIDATION); + } return true; } @@ -338,6 +346,11 @@ release_privatization_lock(my_segnum); } + if (thread_local_for_logging != NULL) { + stop_timer_and_publish_for_thread( + thread_local_for_logging, STM_DURATION_VALIDATION); + } + return !needs_abort; } @@ -346,6 +359,8 @@ { /* puts all modified_old_objects in a new commit log entry */ + start_timer(); + // we don't need the privatization lock, as we are only // reading from modified_old_objs and nobody but us can change it struct list_s *list = STM_PSEGMENT->modified_old_objects; @@ -358,6 +373,9 @@ result->rev_num = -1; /* invalid */ result->written_count = count; memcpy(result->written, list->items, count * sizeof(struct stm_undo_s)); + + stop_timer_and_publish(STM_DURATION_CREATE_CLE); + return result; } @@ -400,6 +418,8 @@ */ static void _validate_and_attach(struct stm_commit_log_entry_s *new) { + start_timer(); + uintptr_t cle_length = 0; struct stm_commit_log_entry_s *old; @@ -412,10 +432,17 @@ soon_finished_or_inevitable_thread_segment(); retry_from_start: + pause_timer(); if (!_stm_validate()) { + continue_timer(); + free_cle(new); - stm_abort_transaction(); + + stop_timer_and_publish(STM_DURATION_VALIDATION); + + stm_abort_transaction(); // leaves method by longjump } + continue_timer(); if (cle_length != list_count(STM_PSEGMENT->modified_old_objects)) { /* something changed the list of modified objs during _stm_validate; or @@ -475,6 +502,8 @@ dprintf(("_validate_and_attach(%p) failed, retrying\n", new)); goto retry_from_start; } + + stop_timer_and_publish(STM_DURATION_VALIDATION); } /* This is called to do stm_validate() and then attach INEV_RUNNING to @@ -495,6 +524,8 @@ static void _validate_and_add_to_commit_log(void) { + start_timer(); + struct stm_commit_log_entry_s *old, *new; new = _create_commit_log_entry(); @@ -523,8 +554,12 @@ release_modification_lock_wr(STM_SEGMENT->segment_num); } else { + pause_timer(); _validate_and_attach(new); + continue_timer(); } + + stop_timer_and_publish(STM_DURATION_VALIDATION); } /* ############# STM ############# */ @@ -817,6 +852,8 @@ static void write_slowpath_common(object_t *obj, bool mark_card) { + start_timer(); + assert(_seems_to_be_running_transaction()); assert(!_is_in_nursery(obj)); assert(obj->stm_flags & GCFLAG_WRITE_BARRIER); @@ -826,6 +863,8 @@ part again: */ assert(!(obj->stm_flags & GCFLAG_WB_EXECUTED)); write_slowpath_overflow_obj(obj, mark_card); + + stop_timer_and_publish(STM_DURATION_WRITE_GC_ONLY); return; } @@ -893,11 +932,15 @@ } DEBUG_EXPECT_SEGFAULT(true); + + stop_timer_and_publish(STM_DURATION_WRITE_SLOWPATH); } void _stm_write_slowpath_card(object_t *obj, uintptr_t index) { + start_timer(); + dprintf_test(("write_slowpath_card(%p, %lu)\n", obj, index)); @@ -906,9 +949,15 @@ card marking instead. */ if (!(obj->stm_flags & GCFLAG_CARDS_SET)) { bool mark_card = obj_should_use_cards(STM_SEGMENT->segment_base, obj); + + pause_timer(); write_slowpath_common(obj, mark_card); - if (!mark_card) + continue_timer(); + + if (!mark_card) { + stop_timer_and_publish(STM_DURATION_WRITE_SLOWPATH); return; + } } assert(obj_should_use_cards(STM_SEGMENT->segment_base, obj)); @@ -955,13 +1004,13 @@ dprintf(("mark %p index %lu, card:%lu with %d\n", obj, index, get_index_to_card_index(index), CARD_MARKED)); + + stop_timer_and_publish(STM_DURATION_WRITE_SLOWPATH); } __attribute__((flatten)) void _stm_write_slowpath(object_t *obj) { - start_timer() write_slowpath_common(obj, /* mark_card */ false); - stop_timer_and_publish(STM_DURATION_WRITE_BARRIER) } @@ -1021,6 +1070,8 @@ static void _do_start_transaction(stm_thread_local_t *tl) { + start_timer(); + assert(!_stm_in_transaction(tl)); tl->wait_event_emitted = 0; @@ -1084,6 +1135,8 @@ reset_transaction_read_version(); } + stop_timer_and_publish(STM_DURATION_START_TRX); + stm_validate(); } @@ -1208,6 +1261,9 @@ static void _core_commit_transaction(bool external) { + start_timer(); + stm_thread_local_t *thread_local_for_logging = STM_SEGMENT->running_thread; + exec_local_finalizers(); assert(!_has_mutex()); @@ -1226,11 +1282,17 @@ assert(STM_SEGMENT->running_thread->wait_event_emitted == 0); dprintf(("> stm_commit_transaction(external=%d)\n", (int)external)); + + pause_timer(); minor_collection(/*commit=*/ true, external); + continue_timer(); + if (!external && is_major_collection_requested()) { s_mutex_lock(); if (is_major_collection_requested()) { /* if still true */ + pause_timer(); major_collection_with_mutex(); + continue_timer(); } s_mutex_unlock(); } @@ -1246,7 +1308,10 @@ stm_validate() at the start of a new transaction is happy even if there is an inevitable tx running) */ bool was_inev = STM_PSEGMENT->transaction_state == TS_INEVITABLE; + + pause_timer(); _validate_and_add_to_commit_log(); + continue_timer(); if (external) { /* from this point on, unlink the original 'stm_thread_local_t *' @@ -1295,6 +1360,9 @@ s_mutex_unlock(); + stop_timer_and_publish_for_thread( + thread_local_for_logging, STM_DURATION_COMMIT_EXCEPT_GC); + /* between transactions, call finalizers. this will execute a transaction itself */ if (tl != NULL) diff --git a/c8/stm/gcpage.c b/c8/stm/gcpage.c --- a/c8/stm/gcpage.c +++ b/c8/stm/gcpage.c @@ -747,9 +747,13 @@ dprintf((" .----- major collection -----------------------\n")); assert(_has_mutex()); + stm_thread_local_t *thread_local_for_logging = STM_SEGMENT->running_thread; + /* first, force a minor collection in each of the other segments */ major_do_validation_and_minor_collections(); + start_timer(); + dprintf((" | used before collection: %ld\n", (long)pages_ctl.total_allocated)); dprintf((" | commit log entries before: %ld\n", @@ -779,9 +783,12 @@ dprintf((" | used after collection: %ld\n", (long)pages_ctl.total_allocated)); dprintf((" `----------------------------------------------\n")); + + stop_timer_and_publish_for_thread( + thread_local_for_logging, STM_DURATION_MAJOR_GC_LOG_ONLY); + if (must_abort()) abort_with_mutex(); - return; #endif } @@ -836,6 +843,10 @@ must abort, do it now. The others are in safe-points that will abort if they need to. */ dprintf(("must abort?:%d\n", (int)must_abort())); + + stop_timer_and_publish_for_thread( + thread_local_for_logging, STM_DURATION_MAJOR_GC_FULL); + if (must_abort()) abort_with_mutex(); } diff --git a/c8/stm/nursery.c b/c8/stm/nursery.c --- a/c8/stm/nursery.c +++ b/c8/stm/nursery.c @@ -534,6 +534,8 @@ static void _do_minor_collection(bool commit) { + start_timer(); + dprintf(("minor_collection commit=%d\n", (int)commit)); assert(!STM_SEGMENT->no_safe_point_here); @@ -578,6 +580,8 @@ throw_away_nursery(get_priv_segment(STM_SEGMENT->segment_num)); assert(MINOR_NOTHING_TO_DO(STM_PSEGMENT)); + + stop_timer_and_publish(STM_DURATION_MINOR_GC); } static void minor_collection(bool commit, bool external) diff --git a/c8/stm/timing.h b/c8/stm/timing.h --- a/c8/stm/timing.h +++ b/c8/stm/timing.h @@ -1,32 +1,48 @@ #include <time.h> +#define continue_timer() clock_gettime(CLOCK_MONOTONIC_RAW, &start); + /* Use raw monotonic time, i.e., solely based on local hardware (no NTP adjustments) as in prof.c to obtain values comparable with total program runtime. */ -#define start_timer() struct timespec start; \ - clock_gettime(CLOCK_MONOTONIC_RAW, &start); +#define start_timer() struct timespec start, stop; \ + struct timespec duration = { .tv_sec = 0, .tv_nsec = 0 };\ + uint32_t nanosec_diff, sec_diff; \ + continue_timer() -#define stop_timer() struct timespec stop; \ - clock_gettime(CLOCK_MONOTONIC_RAW, &stop); +/* Must use start_timer before using this macro. */ +#define get_duration() nanosec_diff = stop.tv_nsec - start.tv_nsec; \ + sec_diff = stop.tv_sec - start.tv_sec; \ + if (stop.tv_nsec < start.tv_nsec) { \ + nanosec_diff += 1000000000; \ + sec_diff -= 1; \ + } \ + duration.tv_sec += sec_diff; \ + duration.tv_nsec += nanosec_diff; \ + if (duration.tv_nsec >= 1000000000) { \ + duration.tv_sec += 1; \ + duration.tv_nsec -= 1000000000; \ + } -/* Must use start_timer and stop_timer before using this macro. */ -#define get_duration() struct timespec duration = { \ - stop.tv_sec - start.tv_sec, \ - stop.tv_nsec - start.tv_nsec \ - }; +#define pause_timer() clock_gettime(CLOCK_MONOTONIC_RAW, &stop); \ + get_duration() -#define stm_duration_payload(duration) \ - stm_timing_event_payload_data_t stm_duration_data = \ - { .duration = &duration }; \ - stm_timing_event_payload_t stm_duration_payload = \ +#define stm_duration_payload(duration) \ + stm_timing_event_payload_data_t stm_duration_data = \ + { .duration = &duration }; \ + stm_timing_event_payload_t stm_duration_payload = \ { STM_EVENT_PAYLOAD_DURATION, stm_duration_data }; -#define publish_event(event) \ - (timing_enabled() ? \ - stmcb_timing_event(STM_SEGMENT->running_thread, event, &stm_duration_payload) : \ +#define publish_event(thread_local, event) \ + (timing_enabled() ? \ + stmcb_timing_event(thread_local, event, &stm_duration_payload) : \ (void)0); -#define stop_timer_and_publish(event) stop_timer() \ - get_duration() \ - stm_duration_payload(duration) \ - publish_event(event) +#define stop_timer_and_publish_for_thread(thread_local, event) \ + pause_timer() \ + stm_duration_payload(duration) \ + assert(thread_local != NULL); \ + publish_event(thread_local, event) + +#define stop_timer_and_publish(event) \ + stop_timer_and_publish_for_thread(STM_SEGMENT->running_thread, event) diff --git a/c8/stmgc.h b/c8/stmgc.h --- a/c8/stmgc.h +++ b/c8/stmgc.h @@ -575,33 +575,41 @@ STM_GC_MAJOR_DONE, /* execution duration profiling events */ - STM_DURATION_WRITE_BARRIER, + STM_DURATION_START_TRX, + STM_DURATION_WRITE_GC_ONLY, + STM_DURATION_WRITE_SLOWPATH, STM_DURATION_VALIDATION, - STM_DURATION_COMMIT, + STM_DURATION_CREATE_CLE, + STM_DURATION_COMMIT_EXCEPT_GC, STM_DURATION_MINOR_GC, - STM_DURATION_MAJOR_GC, + STM_DURATION_MAJOR_GC_LOG_ONLY, + STM_DURATION_MAJOR_GC_FULL, _STM_EVENT_N }; -#define STM_EVENT_NAMES \ - "transaction start", \ - "transaction commit", \ - "transaction abort", \ - "contention write read", \ - "wait free segment", \ - "wait other inevitable", \ - "wait done", \ - "gc minor start", \ - "gc minor done", \ - "gc major start", \ - "gc major done", \ - /* names of duration events */ \ - "duration of write slowpath", \ - "duration of validation", \ - "duration of commit", \ - "duration of minor gc", \ - "duration of major gc" +#define STM_EVENT_NAMES \ + "transaction start", \ + "transaction commit", \ + "transaction abort", \ + "contention write read", \ + "wait free segment", \ + "wait other inevitable", \ + "wait done", \ + "gc minor start", \ + "gc minor done", \ + "gc major start", \ + "gc major done", \ + /* names of duration events */ \ + "duration of transaction start", \ + "duration of gc due to write", \ + "duration of write slowpath", \ + "duration of validation", \ + "duration of commit log entry creation", \ + "duration of commit except gc", \ + "duration of minor gc", \ + "duration of major gc doing log clean up only", \ + "duration of full major gc" /* The markers pushed in the shadowstack are an odd number followed by a regular object pointer. */ _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit