[Gc] adding profiling callbacks
Lucas Meijer <[email protected]> Mon, 30 Jun 2014 10:24:25 +0200
| Newsgroups | gmane.comp.programming.garbage-collection.boehmgc |
|---|---|
| Message-ID | <CAF3RfKqoOec45Vh99WiT8ARVSaOZ92fv4k4Rq3=WCDr9waES2w@mail.gmail.com> |
Hi, Unity is a game development tool that for some platforms uses Boehm to collect garbage generated by our users .NET code. Our builtin profiler can profile all the different game subsystems we have, and I've added support to it for also profiling the boehm collector. I've added profiling callbacks to our version of boehm, and would like to ask this list if there's any interest in taking these patches. (the friendly folks at the mono project did pretty much the same for their fork of boehm). Here's the patches we have now. I'd be more than happy to adapt/fix any concerns they might have. Bye, Lucas _______________________________________________ bdwgc mailing list [email protected] https://lists.opendylan.org/mailman/listinfo/bdwgc
profilingcallbacks.diff
(text/plain, 4.8 KB)
diff --git a/External/bdwgc/alloc.c b/External/bdwgc/alloc.c
--- a/External/bdwgc/alloc.c
+++ b/External/bdwgc/alloc.c
@@ -347,6 +347,18 @@
STATIC GC_bool GC_stopped_mark(GC_stop_func stop_func);
STATIC void GC_finish_collection(void);
+static GC_event_callback_func GC_event_callback = NULL;
+
+void GC_set_event_callback(GC_event_callback_func func)
+{
+ GC_event_callback = func;
+}
+
+GC_event_callback_func GC_get_event_callback()
+{
+ return GC_event_callback;
+}
+
/*
* Initiate a garbage collection if appropriate.
* Choose judiciously
@@ -420,6 +432,10 @@
# endif
ASSERT_CANCEL_DISABLED();
if (GC_dont_gc || (*stop_func)()) return FALSE;
+
+ if (GC_event_callback)
+ GC_event_callback (GC_EVENT_START, NULL);
+
if (GC_incremental && GC_collection_in_progress()) {
GC_COND_LOG_PRINTF(
"GC_try_to_collect_inner: finishing collection in progress\n");
@@ -476,6 +492,10 @@
MS_TIME_DIFF(current_time,start_time));
}
# endif
+
+ if (GC_event_callback)
+ GC_event_callback (GC_EVENT_END, NULL);
+
return(TRUE);
}
@@ -607,10 +627,20 @@
GET_TIME(start_time);
# endif
+ if (GC_event_callback)
+ GC_event_callback (GC_EVENT_PRE_STOP_WORLD, NULL);
+
STOP_WORLD();
# ifdef THREAD_LOCAL_ALLOC
GC_world_stopped = TRUE;
# endif
+
+ if (GC_event_callback)
+ {
+ GC_event_callback (GC_EVENT_POST_STOP_WORLD, NULL);
+ GC_event_callback (GC_EVENT_MARK_START, NULL);
+ }
+
/* Output blank line for convenience here */
GC_COND_LOG_PRINTF(
"\n--> Marking for collection #%lu after %lu allocated bytes\n",
@@ -632,10 +662,19 @@
GC_COND_LOG_PRINTF("Abandoned stopped marking after"
" %u iterations\n", i);
GC_deficit = i; /* Give the mutator a chance. */
+
+ if (GC_event_callback)
+ {
+ GC_event_callback (GC_EVENT_MARK_END, NULL);
+ GC_event_callback (GC_EVENT_PRE_START_WORLD, NULL);
+ }
# ifdef THREAD_LOCAL_ALLOC
GC_world_stopped = FALSE;
# endif
START_WORLD();
+ if (GC_event_callback)
+ GC_event_callback (GC_EVENT_POST_START_WORLD, NULL);
+
return(FALSE);
}
if (GC_mark_some(GC_approx_sp())) break;
@@ -656,7 +695,18 @@
# ifdef THREAD_LOCAL_ALLOC
GC_world_stopped = FALSE;
# endif
+
+ if (GC_event_callback)
+ {
+ GC_event_callback (GC_EVENT_MARK_END, NULL);
+ GC_event_callback (GC_EVENT_PRE_START_WORLD, NULL);
+ }
+
START_WORLD();
+
+ if (GC_event_callback)
+ GC_event_callback (GC_EVENT_POST_START_WORLD, NULL);
+
# ifndef SMALL_CONFIG
if (GC_PRINT_STATS_FLAG) {
unsigned long time_diff;
diff --git a/External/bdwgc/include/gc.h b/External/bdwgc/include/gc.h
--- a/External/bdwgc/include/gc.h
+++ b/External/bdwgc/include/gc.h
@@ -105,6 +105,25 @@
/* Public R/W variables */
/* The supplied setter and getter functions are preferred for new code. */
+typedef enum {
+ GC_EVENT_START,
+ GC_EVENT_MARK_START,
+ GC_EVENT_MARK_END,
+ GC_EVENT_RECLAIM_START,
+ GC_EVENT_RECLAIM_END,
+ GC_EVENT_END,
+ GC_EVENT_PRE_STOP_WORLD,
+ GC_EVENT_POST_STOP_WORLD,
+ GC_EVENT_PRE_START_WORLD,
+ GC_EVENT_POST_START_WORLD,
+ GC_EVENT_SUSPENDED_THREAD,
+ GC_EVENT_UNSUSPENDED_THREAD,
+} GCEventType;
+
+typedef void * (GC_CALLBACK * GC_event_callback_func)(GCEventType eventType, void* data);
+GC_API void GC_CALL GC_set_event_callback(GC_event_callback_func);
+GC_API GC_event_callback_func GC_CALL GC_get_event_callback(void);
+
typedef void * (GC_CALLBACK * GC_oom_func)(size_t /* bytes_requested */);
GC_API GC_ATTR_DEPRECATED GC_oom_func GC_oom_fn;
/* When there is insufficient memory to satisfy */
diff --git a/External/bdwgc/pthread_stop_world.c b/External/bdwgc/pthread_stop_world.c
--- a/External/bdwgc/pthread_stop_world.c
+++ b/External/bdwgc/pthread_stop_world.c
@@ -505,6 +505,9 @@
n_live_threads--;
break;
case 0:
+ GC_get_event_callback_func cb = GC_get_event_callback();
+ if (cb)
+ cb(GC_EVENT_SUSPENDED_THREAD, p->id);
break;
default:
ABORT_ARG1("pthread_kill failed at suspend",
@@ -829,6 +832,9 @@
n_live_threads--;
break;
case 0:
+ GC_get_event_callback_func cb = GC_get_event_callback();
+ if (cb)
+ cb(GC_EVENT_UNSUSPENDED_THREAD, p->id);
break;
default:
ABORT_ARG1("pthread_kill failed at resume",