From c5ae557f0c67cb69ad300ca74d9274e7ed924aa7 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Mon, 3 Jun 2019 14:09:44 -0700 Subject: profiler: record duration of GC sweeps Now that we are using sysprof-capture-3, we can record marks from the various subsystems in GJS. This adds marks to the capture when we perform a GC sweep operation. Related to GNOME/Initiatives#10 --- gjs/context-private.h | 5 ++++- gjs/context.cpp | 20 ++++++++++++++++++++ gjs/profiler-private.h | 4 ++++ gjs/profiler.cpp | 15 +++++++++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) (limited to 'gjs') diff --git a/gjs/context-private.h b/gjs/context-private.h index 10dcf688..274352fa 100644 --- a/gjs/context-private.h +++ b/gjs/context-private.h @@ -117,6 +117,8 @@ class GjsContextPrivate { bool m_should_profile : 1; bool m_should_listen_sigusr2 : 1; + int64_t m_sweep_begin_time; + void schedule_gc_internal(bool force_gc); static gboolean trigger_gc_if_needed(void* data); static gboolean drain_job_queue_idle_handler(void* data); @@ -148,7 +150,6 @@ class GjsContextPrivate { GJS_USE const GjsAtoms& atoms(void) const { return m_atoms; } GJS_USE bool destroying(void) const { return m_destroying; } GJS_USE bool sweeping(void) const { return m_in_gc_sweep; } - void set_sweeping(bool value) { m_in_gc_sweep = value; } GJS_USE const char* program_name(void) const { return m_program_name; } void set_program_name(char* value) { m_program_name = value; } void set_search_path(char** value) { m_search_path = value; } @@ -194,6 +195,8 @@ class GjsContextPrivate { void register_unhandled_promise_rejection(uint64_t id, GjsAutoChar&& stack); void unregister_unhandled_promise_rejection(uint64_t id); + void set_sweeping(bool value); + static void trace(JSTracer* trc, void* data); void free_profiler(void); diff --git a/gjs/context.cpp b/gjs/context.cpp index 0ac7fb68..6e2d54af 100644 --- a/gjs/context.cpp +++ b/gjs/context.cpp @@ -609,6 +609,26 @@ void GjsContextPrivate::schedule_gc_if_needed(void) { schedule_gc_internal(false); } +void GjsContextPrivate::set_sweeping(bool value) { + // If we have a profiler enabled, record the duration of GC sweep + if (this->m_profiler != nullptr) { + int64_t now = g_get_monotonic_time() * 1000L; + + if (value) { + m_sweep_begin_time = now; + } else { + if (m_sweep_begin_time != 0) { + _gjs_profiler_add_mark(this->m_profiler, m_sweep_begin_time, + now - m_sweep_begin_time, "GJS", "Sweep", + nullptr); + m_sweep_begin_time = 0; + } + } + } + + m_in_gc_sweep = value; +} + void GjsContextPrivate::exit(uint8_t exit_code) { g_assert(!m_should_exit); m_should_exit = true; diff --git a/gjs/profiler-private.h b/gjs/profiler-private.h index 20cb9f46..0697be25 100644 --- a/gjs/profiler-private.h +++ b/gjs/profiler-private.h @@ -33,6 +33,10 @@ G_BEGIN_DECLS GjsProfiler *_gjs_profiler_new(GjsContext *context); void _gjs_profiler_free(GjsProfiler *self); +void _gjs_profiler_add_mark(GjsProfiler* self, gint64 time, gint64 duration, + const char* group, const char* name, + const char* message); + GJS_USE bool _gjs_profiler_is_running(GjsProfiler *self); diff --git a/gjs/profiler.cpp b/gjs/profiler.cpp index b332b859..3f35aabb 100644 --- a/gjs/profiler.cpp +++ b/gjs/profiler.cpp @@ -639,3 +639,18 @@ gjs_profiler_set_filename(GjsProfiler *self, g_free(self->filename); self->filename = g_strdup(filename); } + +void _gjs_profiler_add_mark(GjsProfiler* self, gint64 time_nsec, + gint64 duration_nsec, const char* group, + const char* name, const char* message) { + g_return_if_fail(self); + g_return_if_fail(group); + g_return_if_fail(name); + +#ifdef ENABLE_PROFILER + if (self->running && self->capture != nullptr) { + sysprof_capture_writer_add_mark(self->capture, time_nsec, -1, self->pid, + duration_nsec, group, name, message); + } +#endif +} -- cgit v1.2.1