[gjs/wip/chergert/sysprof-3] profiler: add support for GJS_TRACE_FD
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs/wip/chergert/sysprof-3] profiler: add support for GJS_TRACE_FD
- Date: Mon, 3 Jun 2019 21:19:44 +0000 (UTC)
commit f7527842fbffaf422b0a4b09be6715e833c5762b
Author: Christian Hergert <chergert redhat com>
Date: Mon Jun 3 14:10:26 2019 -0700
profiler: add support for GJS_TRACE_FD
This commit adds support for a special environment variable GJS_TRACE_FD.
The console will, in response to this environment variable, enable
tracing of the GJS context and deliver the output to the provided file-
descriptor.
In the upcoming Sysprof-3 branch, this can be used to automatically sample
some GJS-based applications. Applications that use libgjs from a C-based
main() will need to implement the g_getenv() GJS_TRACE_FD manually.
gjs/console.cpp | 20 ++++++++++++++++++++
gjs/profiler.cpp | 33 +++++++++++++++++++++++++++++----
gjs/profiler.h | 2 ++
test/gjs-tests.cpp | 1 +
4 files changed, 52 insertions(+), 4 deletions(-)
---
diff --git a/gjs/console.cpp b/gjs/console.cpp
index 4f876153..2f813c7c 100644
--- a/gjs/console.cpp
+++ b/gjs/console.cpp
@@ -281,10 +281,21 @@ main(int argc, char **argv)
/* This should be removed after a suitable time has passed */
check_script_args_for_stray_gjs_args(script_argc, script_argv);
+ /* Check for GJS_TRACE_FD for sysprof profiling */
+ const char* env_tracefd = g_getenv("GJS_TRACE_FD");
+ int tracefd = -1;
+ if (env_tracefd) {
+ tracefd = g_ascii_strtoll(env_tracefd, nullptr, 10);
+ g_setenv("GJS_TRACE_FD", "", true);
+ if (tracefd > 0)
+ enable_profiler = true;
+ }
+
if (interactive_mode && enable_profiler) {
g_message("Profiler disabled in interactive mode.");
enable_profiler = false;
g_unsetenv("GJS_ENABLE_PROFILER"); /* ignore env var in eval() */
+ g_unsetenv("GJS_TRACE_FD"); /* ignore env var in eval() */
}
js_context = (GjsContext*) g_object_new(GJS_TYPE_CONTEXT,
@@ -318,6 +329,15 @@ main(int argc, char **argv)
if (enable_profiler && profile_output_path) {
GjsProfiler *profiler = gjs_context_get_profiler(js_context);
gjs_profiler_set_filename(profiler, profile_output_path);
+ } else if (enable_profiler && tracefd > -1) {
+ GjsProfiler* profiler = gjs_context_get_profiler(js_context);
+ gjs_profiler_set_fd(profiler, tracefd);
+ tracefd = -1;
+ }
+
+ if (tracefd != -1) {
+ close(tracefd);
+ tracefd = -1;
}
/* prepare command line arguments */
diff --git a/gjs/profiler.cpp b/gjs/profiler.cpp
index a6883aaf..7a1f5e3d 100644
--- a/gjs/profiler.cpp
+++ b/gjs/profiler.cpp
@@ -28,6 +28,7 @@
#include <memory>
#include <signal.h>
#include <sys/types.h>
+#include <unistd.h>
#include "jsapi-wrapper.h"
#include <js/ProfilingStack.h>
@@ -101,6 +102,9 @@ struct _GjsProfiler {
/* The filename to write to */
char *filename;
+ /* An FD to capture to */
+ int fd;
+
#ifdef ENABLE_PROFILER
/* Our POSIX timer to wakeup SIGPROF */
timer_t timer;
@@ -219,6 +223,7 @@ _gjs_profiler_new(GjsContext *context)
self->cx = static_cast<JSContext *>(gjs_context_get_native_context(context));
self->pid = getpid();
#endif
+ self->fd = -1;
profiling_context = context;
@@ -245,6 +250,9 @@ _gjs_profiler_free(GjsProfiler *self)
profiling_context = nullptr;
+ if (self->fd != -1)
+ close(self->fd);
+
g_clear_pointer(&self->filename, g_free);
#ifdef ENABLE_PROFILER
g_clear_pointer(&self->capture, sysprof_capture_writer_unref);
@@ -402,11 +410,16 @@ gjs_profiler_start(GjsProfiler *self)
struct itimerspec its = { 0 };
struct itimerspec old_its;
- GjsAutoChar path = g_strdup(self->filename);
- if (!path)
- path = g_strdup_printf("gjs-%jd.syscap", intmax_t(self->pid));
+ if (self->fd != -1) {
+ self->capture = sysprof_capture_writer_new_from_fd(self->fd, 0);
+ self->fd = -1;
+ } else {
+ GjsAutoChar path = g_strdup(self->filename);
+ if (!path)
+ path = g_strdup_printf("gjs-%jd.syscap", intmax_t(self->pid));
- self->capture = sysprof_capture_writer_new(path, 0);
+ self->capture = sysprof_capture_writer_new(path, 0);
+ }
if (!self->capture) {
g_warning("Failed to open profile capture");
@@ -652,3 +665,15 @@ void _gjs_profiler_add_mark(GjsProfiler* self, gint64 time_nsec,
duration_nsec, group, name, message);
}
}
+
+void gjs_profiler_set_fd(GjsProfiler* self, int fd) {
+ g_return_if_fail(self);
+ g_return_if_fail(!self->filename);
+ g_return_if_fail(!self->running);
+
+ if (self->fd != fd) {
+ if (self->fd != -1)
+ close(self->fd);
+ self->fd = fd;
+ }
+}
diff --git a/gjs/profiler.h b/gjs/profiler.h
index 8bebed25..95615bd4 100644
--- a/gjs/profiler.h
+++ b/gjs/profiler.h
@@ -40,6 +40,8 @@ GType gjs_profiler_get_type(void);
GJS_EXPORT
void gjs_profiler_set_filename(GjsProfiler *self,
const char *filename);
+GJS_EXPORT
+void gjs_profiler_set_fd(GjsProfiler* self, int fd);
GJS_EXPORT
void gjs_profiler_start(GjsProfiler *self);
diff --git a/test/gjs-tests.cpp b/test/gjs-tests.cpp
index d438b615..4ab3f8d6 100644
--- a/test/gjs-tests.cpp
+++ b/test/gjs-tests.cpp
@@ -391,6 +391,7 @@ main(int argc,
{
/* Avoid interference in the tests from stray environment variable */
g_unsetenv("GJS_ENABLE_PROFILER");
+ g_unsetenv("GJS_TRACE_FD");
g_test_init(&argc, &argv, NULL);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]