[gjs] gjs_maybe_gc: mallinfo() is slow, look at /proc/self/statm instead
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] gjs_maybe_gc: mallinfo() is slow, look at /proc/self/statm instead
- Date: Thu, 10 Mar 2011 20:22:29 +0000 (UTC)
commit 7aae32d1df14af87e9a31c785447b27012b64af9
Author: Colin Walters <walters verbum org>
Date: Thu Mar 3 09:10:13 2011 -0500
gjs_maybe_gc: mallinfo() is slow, look at /proc/self/statm instead
In commit 45b550d6790dba70, we introduced a function which
attempts to force a JavaScript GC if native malloc() had allocated
a lot. The major flaw with this is that on medium size processes
(e.g. gnome-shell), mallinfo *is* slow. I'd only benchmarked
it on smaller ones.
Rather than looking at malloc, a simpler and definitely faster
way to reflect on our process' memory impact is to look at RSS.
Also, don't call gjs_maybe_gc() internally; leave it up to
embedders to invoke manually.
https://bugzilla.gnome.org/show_bug.cgi?id=643817
gi/boxed.c | 4 --
gi/object.c | 2 -
gjs/jsapi-util.c | 85 +++++++++++++++++++++++++++++++++++++----------------
3 files changed, 59 insertions(+), 32 deletions(-)
---
diff --git a/gi/boxed.c b/gi/boxed.c
index 405baaa..268d629 100644
--- a/gi/boxed.c
+++ b/gi/boxed.c
@@ -490,7 +490,6 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(boxed)
GType gtype = g_registered_type_info_get_g_type( (GIRegisteredTypeInfo*) priv->info);
if (gtype != G_TYPE_NONE) {
priv->gboxed = g_boxed_copy(gtype, source_priv->gboxed);
- gjs_maybe_gc(context);
GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
return JS_TRUE;
}
@@ -545,7 +544,6 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(boxed)
}
unthreadsafe_template_for_constructor.gboxed = NULL;
- gjs_maybe_gc(context);
retval = priv->gboxed != NULL;
if (retval)
@@ -554,8 +552,6 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(boxed)
}
}
- gjs_maybe_gc(context);
-
GJS_NATIVE_CONSTRUCTOR_FINISH(boxed);
return JS_TRUE;
diff --git a/gi/object.c b/gi/object.c
index 25b561a..b55d743 100644
--- a/gi/object.c
+++ b/gi/object.c
@@ -771,8 +771,6 @@ GJS_NATIVE_CONSTRUCTOR_DECLARE(object_instance)
GJS_NATIVE_CONSTRUCTOR_FINISH(object_instance);
- gjs_maybe_gc(context);
-
return JS_TRUE;
}
diff --git a/gjs/jsapi-util.c b/gjs/jsapi-util.c
index 97e359b..cec3304 100644
--- a/gjs/jsapi-util.c
+++ b/gjs/jsapi-util.c
@@ -34,9 +34,6 @@
#include <string.h>
#include <math.h>
-#ifdef HAVE_MALLOC_H
-#include <malloc.h>
-#endif
GQuark
gjs_util_error_quark (void)
@@ -1523,6 +1520,41 @@ gjs_parse_args (JSContext *context,
return JS_FALSE;
}
+#ifdef __linux__
+static void
+_linux_get_self_process_size (gulong *vm_size,
+ gulong *rss_size)
+{
+ char *contents;
+ char *iter;
+ gsize len;
+ int i;
+
+ *vm_size = *rss_size = 0;
+
+ if (!g_file_get_contents ("/proc/self/stat", &contents, &len, NULL))
+ return;
+
+ iter = contents;
+ /* See "man proc" for where this 22 comes from */
+ for (i = 0; i < 22; i++) {
+ iter = strchr (iter, ' ');
+ if (!iter)
+ goto out;
+ iter++;
+ }
+ sscanf (iter, " %lu", vm_size);
+ iter = strchr (iter, ' ');
+ if (iter)
+ sscanf (iter, " %lu", rss_size);
+
+ out:
+ g_free (contents);
+}
+
+static gulong linux_rss_trigger;
+#endif
+
/**
* gjs_maybe_gc:
*
@@ -1531,32 +1563,33 @@ gjs_parse_args (JSContext *context,
void
gjs_maybe_gc (JSContext *context)
{
- /* Picked this number out of the air basically; 16 megabytes
- * "feels" good for all of mobile/embedded/GP. We don't
- * expect the cost of JS_GC() to be too high, but we
- * also don't want to call it too often.
- *
- * A better approach actually may be to dynamically watch "free";
- * how much memory we're using before we hit swap. Even better of
- * course: some component of the OS sends us a signal when we
- * should be trying a GC.
- */
-#define _GJS_MAYBE_GC_MALLOC_BYTES (16 * 1024 * 1024)
-
- static int _gjs_last_maybe_gc_malloc_blocks = -1;
-
JS_MaybeGC(context);
-#ifdef HAVE_MALLINFO
+#ifdef __linux__
{
- struct mallinfo mstats;
- mstats = mallinfo();
- if (mstats.uordblks < _gjs_last_maybe_gc_malloc_blocks || _gjs_last_maybe_gc_malloc_blocks == -1) {
- _gjs_last_maybe_gc_malloc_blocks = mstats.uordblks;
- } else if ((mstats.uordblks - _gjs_last_maybe_gc_malloc_blocks) > _GJS_MAYBE_GC_MALLOC_BYTES) {
+ /* We initiate a GC if VM or RSS has grown by this much */
+ gulong vmsize;
+ gulong rss_size;
+
+ _linux_get_self_process_size (&vmsize, &rss_size);
+
+ /* linux_rss_trigger is initialized to 0, so currently
+ * we always do a full GC early.
+ *
+ * Here we see if the RSS has grown by 25% since
+ * our last look; if so, initiate a full GC. In
+ * theory using RSS is bad if we get swapped out,
+ * since we may be overzealous in GC, but on the
+ * other hand, if swapping is going on, better
+ * to GC.
+ */
+ if (rss_size > linux_rss_trigger) {
+ linux_rss_trigger = (gulong) MIN(G_MAXULONG, rss_size * 1.25);
JS_GC(context);
- _gjs_last_maybe_gc_malloc_blocks = mstats.uordblks;
+ } else if (rss_size < (0.75 * linux_rss_trigger)) {
+ /* If we've shrunk by 75%, lower the trigger */
+ linux_rss_trigger = (rss_size * 1.25);
}
- }
-#endif
+ }
+#endif
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]