After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 354457 - Feature Proposal: Per-Type Statistics for Instantiable GTypes
Feature Proposal: Per-Type Statistics for Instantiable GTypes
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: gobject
2.22.x
Other All
: Normal normal
: ---
Assigned To: Tim Janik
gtkdev
Depends on:
Blocks: 738272
 
 
Reported: 2006-09-05 16:01 UTC by Matthew Barnes
Modified: 2014-10-11 17:56 UTC
See Also:
GNOME target: ---
GNOME version: 2.27/2.28


Attachments
Proposed patch (5.23 KB, patch)
2006-09-05 16:04 UTC, Matthew Barnes
none Details | Review
Revised patch (5.23 KB, patch)
2006-10-22 01:03 UTC, Matthew Barnes
none Details | Review
Sample output (20.10 KB, text/plain)
2006-10-22 01:09 UTC, Matthew Barnes
  Details
Revised patch (4.91 KB, patch)
2007-03-02 04:49 UTC, Matthew Barnes
none Details | Review
Post-processing script (1.62 KB, patch)
2007-03-02 04:53 UTC, Matthew Barnes
none Details | Review
Patch including Python script (11.36 KB, patch)
2007-06-18 19:19 UTC, Matthew Barnes
none Details | Review
Manual page (DocBook) (2.29 KB, text/xml)
2007-09-19 19:48 UTC, Matthew Barnes
  Details
Revised patch (11.03 KB, patch)
2007-11-09 20:01 UTC, Matthew Barnes
none Details | Review
Revised patch (19.08 KB, patch)
2009-01-02 14:46 UTC, Matthew Barnes
none Details | Review
Original patch, updated for GLib 2.28 (13.38 KB, patch)
2011-03-09 22:11 UTC, Matthew Barnes
none Details | Review
Enhanced patch for GLib 2.28 (13.64 KB, patch)
2011-03-09 22:31 UTC, Matthew Barnes
none Details | Review
glib memtrace systemtap script (2.14 KB, text/plain)
2011-03-16 14:54 UTC, Colin Walters
  Details
Updated patch for GLib 2.33 (13.66 KB, patch)
2012-06-24 18:13 UTC, Matthew Barnes
none Details | Review
Add simple instance count facility (4.21 KB, patch)
2014-10-09 21:05 UTC, Owen Taylor
reviewed Details | Review
Add simple instance count facility (4.78 KB, patch)
2014-10-10 19:15 UTC, Matthias Clasen
committed Details | Review
Make instance counting unconditional (2.40 KB, patch)
2014-10-10 19:20 UTC, Matthias Clasen
none Details | Review

Description Matthew Barnes 2006-09-05 16:01:15 UTC
I'd like to propose a new debugging feature for GObject:

Per-Type Statistics for Instantiable GTypes

By trapping calls to g_type_create_instance() and g_type_free_instance(), GObject's type system can keep some useful statistics about instantiable GTypes, including the number of instances created and freed, and the maximum population of a particular type.

This information could be used in several ways:

1) To help with performance tuning or memory usage analysis.
   For example, a large number of instances of a particular type
   being created and destroyed but with a small maximum population
   may indicate an opportunity for boosting performance by caching
   instances of that type.
2) To help find memory leaks (complements GObject's existing "stale
   references" debugging feature).
3) Provides an easy way to check what types an application is using.

The statistics for each type would be output at program exit using g_message(), in alphabetical order by type name.

Example Output:
GLib-GObject-Message: <type-name> (<n> created / <n> destroyed), max population=<n>

The feature would be activated the same way as GObject's other run-time debugging features: by passing a new debug flag (G_TYPE_DEBUG_TYPES) to g_type_init_with_debug_flags(), or setting the environment variable GOBJECT_DEBUG to "types".
Comment 1 Matthew Barnes 2006-09-05 16:04:38 UTC
Created attachment 72257 [details] [review]
Proposed patch
Comment 2 Matthew Barnes 2006-10-22 01:03:27 UTC
Created attachment 75169 [details] [review]
Revised patch

I made the output format easier to parse.  It now looks like:

GLib-GObject-Message: <type-name> | created <n> | destroyed <n> | max population <n>
Comment 3 Matthew Barnes 2006-10-22 01:09:23 UTC
Created attachment 75170 [details]
Sample output

Sample output of an Evolution session.
Comment 4 Tim Janik 2007-03-01 13:57:47 UTC
Comment on attachment 75169 [details] [review]
Revised patch

thanks, very interesting submission. i'd still like to see some details reworked however.

> @G_TYPE_DEBUG_OBJECTS: Print messages about object bookkeeping.

this should better be changed to "Print messages about stale GObjects" to differentiate from your new bookkeeping.

> @G_TYPE_DEBUG_SIGNALS: Print messages about signal emissions.
>+@G_TYPE_DEBUG_TYPES: Print messages about type bookkeeping.

you're really bookkeeping instance and destruction so this should better say:
  +@G_TYPE_DEBUG_TYPES: Print messages about instance bookkeeping.

>+static gboolean
>+debug_types_foreach (gpointer key,
>+                     gpointer value,
>+                     gpointer user_data)
>+{
>+  GType type = GPOINTER_TO_SIZE (key);
>+  DebugTypeStats *stats = value;
>+
>+  g_message ("%s | created %u | destroyed %u | max population %u",
>+             g_type_name (type), stats->num_created, stats->num_destroyed,
>+             stats->max_population);

i don't think the current output format is very useful. while the collected stats are definitely interesting, i think they should be presented in a different format to make the interesting data more easily accessible.
i'd suggest to sort the output by 1) max_population and 2) n_created, and then print these out like:
  GLib-GObject-Message: max_population | n_created | n_destroyed | Instance Type
  GLib-GObject-Message:             11 |        86 |          86 | AtkRelationSet
  GLib-GObject-Message:             10 |        68 |          68 | AtkNoOpObject
  GLib-GObject-Message:              1 |         1 |           0 | AddressbookComponent
  GLib-GObject-Message:              1 |         0 |           1 | AtkNoOpObjectFactory

>@@ -3463,6 +3544,14 @@ g_type_init_with_debug_flags (GTypeDebug
>   /* Signal system
>    */
>   g_signal_init ();
>+
>+#ifdef G_ENABLE_DEBUG
>+  IF_DEBUG (TYPES)
>+    {
>+      debug_types_tree = g_tree_new (debug_types_compare);
>+      g_atexit (debug_types_atexit);

hm, i'd really expect a HashTable to be faster for these kind of lookups, which is why the otehr debugging features use hash tables to store this kind of information. have you tried this by any chance or are willing to reworke the patch some and profile if a hash table is faster?

>+    }
>+#endif
>   
>   G_UNLOCK (type_init_lock);
> }
Comment 5 Matthew Barnes 2007-03-01 18:17:01 UTC
Tim, thanks for reviewing.  I'll clarify some of my rationale, though I'm willing to rework any aspect of the patch as necessary.

I used a GTree in order to easily display the type names alphabetically at program termination, since one may only be interested in types from a particular library or application.  Alphabetized type names tend to be grouped this way due to our naming convention.

I agree that a GHashTable is likely faster for lookups and insertions.  But this being a debugging feature that has to be explicitly turned on, performance was not my highest priority.  Keeping the additional code simple and unobtrusive was.

With respect to formatting, I expect the output would likely be post-processed.  So I was trying to format the output in such a way that it could easily be parsed or piped to the appropriate tools, though I'm not sure my formatting choices are optimal for that purpose.  Admittedly the output looks a bit raw.  The "stale GObject" output appears to be more parsable than readable, and is also unsorted. That served as a precedent.

That said, I'll revise the patch with your suggestions.
Comment 6 Tim Janik 2007-03-01 18:49:01 UTC
(In reply to comment #5)
> I used a GTree in order to easily display the type names alphabetically at
> program termination, since one may only be interested in types from a
> particular library or application.  Alphabetized type names tend to be grouped
> this way due to our naming convention.

oh, very good point, that didn't occour to me.

> With respect to formatting, I expect the output would likely be post-processed.

you can make me shut up about hashtable/sorting if you also attach something like e.g. a python script for post-processing. that'd ideally produce something like the output i suggested above ;)

> Admittedly the output looks a bit raw. 
> The "stale GObject" output appears to be more parsable than readable, and is
> also unsorted. That served as a precedent.

i pled guilty for committing the output formatting of the stale object output. i still think the output i suggested above (maybe after post-processing) would make the result presentaiton of your stats much more useful for users.
Comment 7 Matthew Barnes 2007-03-02 04:49:20 UTC
Created attachment 83710 [details] [review]
Revised patch

Revised patch with suggested documentation changes.
Comment 8 Matthew Barnes 2007-03-02 04:53:56 UTC
Created attachment 83711 [details] [review]
Post-processing script

Post-processing script reads instance statistics from stdin and prints a report similar to what Tim suggested in comment #4.  The script is pretty bare bones; it has no command-line options and poor error handling.
Comment 9 Matthew Barnes 2007-04-07 03:36:32 UTC
Tim: ping, are there any other details you'd like me to rework?
Comment 10 Tim Janik 2007-04-13 11:45:45 UTC
hm, i'm a lazy bumm and was hoping for the script to improve a bit by waiting ;)
do you think you can clean it up a bit (e.g. have help, get a manual page) so it's good enough to be included in the glib tarball and installed under /usr/bin// ?
Comment 11 Matthew Barnes 2007-04-13 13:47:29 UTC
Ah, I didn't realize that was the intent.

I can work on making the Python script production quality.  But would packaging it with GLib introduce a dependency on Python?  Should I first rewrite the script as a C program?
Comment 12 Tim Janik 2007-04-13 14:04:51 UTC
(In reply to comment #11)
> Ah, I didn't realize that was the intent.
> 
> I can work on making the Python script production quality.  But would packaging
> it with GLib introduce a dependency on Python?

strictly speaking, yes.

>  Should I first rewrite the
> script as a C program?

no. we already "depend" on perl by installing perl scripts as build tools (glib-mkenum). i think the script should just be held reasonably portable in python (i.e. support python2.4) and the manual page should say that you need python for this. that's good enough then.

the reason to not have this in C is that it should be easily adaptable in the future and string (post-)processing is *much* simpler in python than in C. also, for an occasioanlly used devel-phase post processing script, C is simply not worth the effort.
Comment 13 Matthew Barnes 2007-04-13 14:56:44 UTC
(In reply to comment #12)
> the reason to not have this in C is that it should be easily adaptable in the
> future and string (post-)processing is *much* simpler in python than in C.
> also, for an occasioanlly used devel-phase post processing script, C is simply
> not worth the effort.

Definitely agree (GRegex notwithstanding).  Thanks for clarifying.
Comment 14 Tim Janik 2007-06-15 08:56:30 UTC
(In reply to comment #11)
> Ah, I didn't realize that was the intent.
> 
> I can work on making the Python script production quality.

(In reply to comment #13)
> (In reply to comment #12)
> > the reason to not have this in C is that it should be easily adaptable in the
> > future and string (post-)processing is *much* simpler in python than in C.
> 
> Definitely agree (GRegex notwithstanding).  Thanks for clarifying.

ok, for the record, i'm still waiting on the production quality python script and manual page then ;)
Comment 15 Matthew Barnes 2007-06-15 13:22:12 UTC
Right, still trying to find time.  Perhaps this weekend...
Comment 16 Matthew Barnes 2007-06-18 19:19:07 UTC
Created attachment 90227 [details] [review]
Patch including Python script

Here's a revised patch that includes a first cut at a production quality Python script (gobjectdebugtypes) to post process the debug messages.

$ gobjectdebugtypes --help
Usage: gobjectdebugtypes [options] [FILE...]

Generate a nicely formatted report from the debugging messages triggered by
setting GObject's G_TYPE_DEBUG_TYPES debug flag.  See the GTypeDebugFlags
section of the GObject Reference Manual to learn how to set this flag.

Options:
  -h, --help            show this help message and exit
  -s COL, --sort-ascending=COL
                        sort column COL in ascending order, where COL is one
                        of "type", "population", "created", or "destroyed"
  -S COL, --sort-descending=COL
                        sort column COL in descending order, where COL is one
                        of "type", "population", "created", or "destroyed"


If you don't provide a filename argument, the script reads from stdin.

You can build the sorting criteria by giving multiple sort options.  The default sorting behavior follows your original suggestion, and is equivalent to invoking:

   $ gobjectdebugtypes -S population -S created -s type

Can you think of any other options that would be useful?
Comment 17 Matthew Barnes 2007-06-18 19:20:39 UTC
Forgot to mention that I'm still working on a manual page, but I wanted to get your thoughts on the script first.  I'll post another patch when it's done.
Comment 18 Matthew Barnes 2007-09-19 19:48:42 UTC
Created attachment 95860 [details]
Manual page (DocBook)

Here's a first cut at a long overdue manual page for the Python utility.  Despite my best efforts, docbook2man chokes on it and I can't make sense of the gibbish it spews:

Using catalogs: /etc/sgml/sgml-docbook-3.0-1.0-31.cat
Using stylesheet: /usr/share/sgml/docbook/utils-0.6.14/docbook-utils.dsl#print
Working on: /home/mbarnes/svn/work/gobject-debug/glib/docs/reference/gobject/gobjectdebugtypes.xml
nsgmls:/home/mbarnes/svn/work/gobject-debug/glib/docs/reference/gobject/gobjectdebugtypes.xml:1:0:E: prolog can't be omitted unless CONCUR NO and LINK EXPLICIT NO and either IMPLYDEF ELEMENT YES or IMPLYDEF DOCTYPE YES
nsgmls:/home/mbarnes/svn/work/gobject-debug/glib/docs/reference/gobject/gobjectdebugtypes.xml:1:0:E: no document type declaration; will parse without validation
Can't call method "value" on an undefined value at /usr/share/sgml/docbook/utils-0.6.14/helpers/docbook2man-spec.pl line 249, <STDIN> line 2.
Comment 19 Matthew Barnes 2007-09-19 19:50:02 UTC
Tim, did you ever get a chance to look at the Python script?
Comment 20 Matthew Barnes 2007-11-09 20:01:29 UTC
Created attachment 98837 [details] [review]
Revised patch

This patch contains everything discussed above:

  - GObject source code changes
  - Report generation utility (gobject-stats)
  - Manual page (both docbook and generated troff)
  - Gtk-Doc updates

Let me know if you spot any outstanding issues.
Comment 21 Matthew Barnes 2008-03-17 14:56:36 UTC
I had occasion to wish for this feature again recently as I was debugging some reference counting leaks in Evolution.

Tim, ping.
Comment 22 Matthew Barnes 2008-05-28 00:41:07 UTC
Matthias, any interest in picking this up for GLib 2.17?

I never got any feedback on the Python script that Tim asked for.
Comment 23 Tim Janik 2008-05-28 11:55:17 UTC
> I never got any feedback on the Python script that Tim asked for.

Sorry, it's still in my queue though ;)

Comment 24 Behdad Esfahbod 2009-01-02 06:10:33 UTC
This feature is so useful.  Can we get it committed in whatever state it is please?
Comment 25 Behdad Esfahbod 2009-01-02 06:26:22 UTC
Humm, Matthew, the patch seems to be missing the python script.
Comment 26 Behdad Esfahbod 2009-01-02 06:30:34 UTC
Just want to add that the output is extremely useful even without any post-processing script.
Comment 27 Matthew Barnes 2009-01-02 13:25:26 UTC
(In reply to comment #25)
> Humm, Matthew, the patch seems to be missing the python script.

Sorry about that, trying now to pull it off a dying laptop.

Patch in comment #16 contains a mostly up-to-date version of the script under a different filename.  I had since renamed it to 'gobject-stats'.
Comment 28 Matthew Barnes 2009-01-02 14:46:34 UTC
Created attachment 125648 [details] [review]
Revised patch

Patch against current SVN trunk.  Includes the Python script this time.
Comment 29 Matthew Barnes 2009-01-02 15:01:08 UTC
(In reply to comment #28)
> Patch against current SVN trunk.  Includes the Python script this time.

Grrr, but now I left out the SGML files for the API docs.
Those are available in the previous patch.
Comment 30 André Klapper 2009-08-11 15:09:05 UTC
Can we get this committed please?
Comment 31 Colin Walters 2009-09-16 18:25:42 UTC
Hello bugzilla CC list,

I needed to debug some GNOME Shell memory usage and was pointed at this patch, and I found it *very* useful.  However, the data it gave made me want more data.

There are a few things I want to improve with this:

1) Specifically for the shell, the environment variable approach is a bit painful because it gets inherited (well, I suppose we could unset it), and a flag for g_type_init is hard because we're a plugin

2) I want the data at multiple points in the program, not just at exit.  For example, how does the just-started state compare to at exit?

3) I really, really want backtraces.

To solve 1) and 2), I rewrote this design as an LD_PRELOADable library.  It temporarily lives here:

http://gitorious.org/gobject-memtrace/gobject-memtrace/commits/master

I'd like to rewrite this as a glib patch; the basic idea is that we'd have:

/usr/bin/gobject-memtrace
/usr/lib64/glib/libgobject-memtrace.so

Where gobject-memtrace is a small shell script which just sets up LD_PRELOAD and probably sets up print-on-exit by default.


What I'm going to work on now is 3), backtraces sorted by frequency.
Comment 32 Owen Taylor 2009-09-16 19:10:56 UTC
Hmm, if it's going into GLib, I dont' think it should be a preload. LD_PRELOAD is inherently unreliable (especially with hiding of symbols from the PLT, etc) and specific to particular platforms.

GLib can unset the variable after reading it at GObject initialization if you want to avoid inheritance.

And doing it in GLib is going to make it much easier to add g_object_dump_type_statistics() hooks that can be run by an application. I don't actually see how writing a LD_PRELOAD library solves 2).

A separate wrapper program that sets an enviroment variable (maybe pointing to an extra FD to avoid overloading stdout) collects the backtraces and saves them nicely formatted might still make sense.
Comment 33 Colin Walters 2009-09-16 19:26:52 UTC
(In reply to comment #32)
> Hmm, if it's going into GLib, I dont' think it should be a preload. LD_PRELOAD
> is inherently unreliable (especially with hiding of symbols from the PLT, etc)
> and specific to particular platforms.

Well, we can also add specific hooks.

> GLib can unset the variable after reading it at GObject initialization if you
> want to avoid inheritance.
> 
> And doing it in GLib is going to make it much easier to add
> g_object_dump_type_statistics() hooks that can be run by an application. I
> don't actually see how writing a LD_PRELOAD library solves 2).

The way I saw this working was an application author wants control over access to the data during application runtime (say in shell, do "lg", "global.dump_perf_data()") they would sets up their launching script to run "gobject-memtrace myapp", then inside their C do do dlsym(NULL, "gobject_memtrace_dump") and call it.

This is a bit more painful for app authors, but on the other hand we avoid adding API to glib.  The other minor point is that gobject_memtrace_dump takes a GOutputStream, which would be hard to do in gobject.

> A separate wrapper program that sets an enviroment variable (maybe pointing to
> an extra FD to avoid overloading stdout) collects the backtraces and saves them
> nicely formatted might still make sense.

Hm, the wrapper program would open a fd itself or something, make sure it's not cloexec, then exec the app?   That won't work on Windows either...
Comment 34 Colin Walters 2009-09-16 19:31:26 UTC
Certainly I don't know what the right way to do backtraces on Windows/OS X are, and for that matter nor the BSDs.  So if the constraint is that all debugging tools in GLib need to be fully crossplatform, then yes, that would be a definite blocker.
Comment 35 Behdad Esfahbod 2009-09-16 19:53:25 UTC
Colin, also see cairo/util/malloc-stats.c

Re backtraces, see glib/glib/gbacktrace.c
Comment 36 Benjamin Otte (Company) 2009-09-16 19:54:59 UTC
I think I came to the conclusion that adding debugging APIs to glib is bad, because they are almost never good enough to solve the problem that you are currently looking at.

It's almost always preferrable to use other means, because those aren't affected by API stability and don't need to be maintained if it turns out that they are not useful (Anyone still doing "free (malloc (4))" in main()?).

The same goes for bug 588139.

Colin, did you mean to up the importance of the bug?
Comment 37 Colin Walters 2009-09-16 20:13:33 UTC
(In reply to comment #35)
> Colin, also see cairo/util/malloc-stats.c

Interesting.  Sort of similar to what I want to do; GLib could provide a __gobject_allocation_hook, and then I could write arbitrary code using that.

> Re backtraces, see glib/glib/gbacktrace.c

Ah, uses gdb.  A bit more crossplatform, however it would be hideously slow for what I want.  Though it would also likely be more accurate than what libc's backtrace_symbols() does.  Hmm...maybe that could be reworked into a persistent "slave gdb process" mode.

(In reply to comment #36)
> I think I came to the conclusion that adding debugging APIs to glib is bad,
> because they are almost never good enough to solve the problem that you are
> currently looking at.

Yeah, there are a variety of concerns; my main one is that dumping to stdout is just not good enough.

> Colin, did you mean to up the importance of the bug?

I accidentally hit the "bad_stacktrace" button and that had all sorts of weird effects.
Comment 38 Behdad Esfahbod 2009-09-16 21:02:49 UTC
My experience with malloc-stat.c is that even backtrace_symbols() is really slow.
Comment 39 Colin Walters 2009-09-16 21:18:05 UTC
(In reply to comment #38)
> My experience with malloc-stat.c is that even backtrace_symbols() is really
> slow.

I'm using just backtrace() in the fast path, and only converting with backtrace_symbols when printing.  Surely backtrace() is relatively fast, it just walks the stack, doesn't need to do any ELF processing.  At least I assume that's the reason for the separation.
Comment 40 Colin Walters 2009-09-16 22:30:47 UTC
Ok, new code landed in gobject-memtrace.  Sample output from:

$ env GMEMTRACE_ATEXIT=1 LD_PRELOAD=./gobject-memtrace.so gedit

FileInfo | created 61 | destroyed 61
  (27 stack traces below threshold 20 omitted)

GtkSourceStyle | created 430 | destroyed 0
  Stack: 21 hits
    ./gobject-memtrace.so [0x7fe6e5a9e171]
    ./gobject-memtrace.so(g_object_new+0xec) [0x7fe6e5a9e388]
    /usr/lib64/libgtksourceview-2.0.so.0(gtk_source_style_copy+0x1e) [0x3c09e23f5e]
    /usr/lib64/libgtksourceview-2.0.so.0(gtk_source_style_scheme_get_style+0x131) [0x3c09e25ec1]
    /usr/lib64/libgtksourceview-2.0.so.0 [0x3c09e26479]
    /usr/lib64/libgtksourceview-2.0.so.0 [0x3c09e24c98]
    /usr/lib64/libgtksourceview-2.0.so.0(gtk_source_style_scheme_manager_get_scheme+0x65) [0x3c09e24fa5]
    /usr/lib64/libgtksourceview-2.0.so.0 [0x3c09e10992]
    /lib64/libgobject-2.0.so.0(g_type_create_instance+0xe8) [0x3c06e2ba58]
    /lib64/libgobject-2.0.so.0 [0x3c06e10a0c]
    /usr/lib64/libgtksourceview-2.0.so.0 [0x3c09e10127]
    /lib64/libgobject-2.0.so.0(g_object_newv+0x291) [0x3c06e11a01]
    /lib64/libgobject-2.0.so.0(g_object_new_valist+0x345) [0x3c06e12555]
    ./gobject-memtrace.so(g_object_new+0xd6) [0x7fe6e5a9e372]
    gedit(gedit_document_new+0x32) [0x430d22]
    gedit [0x4436fa]
    /lib64/libgobject-2.0.so.0(g_type_create_instance+0x137) [0x3c06e2baa7]
    /lib64/libgobject-2.0.so.0 [0x3c06e10a0c]
    /lib64/libgobject-2.0.so.0(g_object_newv+0x291) [0x3c06e11a01]
    /lib64/libgobject-2.0.so.0(g_object_new_valist+0x345) [0x3c06e12555]
    ./gobject-memtrace.so(g_object_new+0xd6) [0x7fe6e5a9e372]
    gedit(_gedit_tab_new+0x1a) [0x442f8a]
    gedit(gedit_window_create_tab+0x7d) [0x44e07d]
    gedit(main+0x55e) [0x4284de]
    /lib64/libc.so.6(__libc_start_main+0xfd) [0x3fa721ea2d]
    gedit [0x427849]
  Stack: 194 hits
    ./gobject-memtrace.so [0x7fe6e5a9e171]
    ./gobject-memtrace.so(g_object_new+0xec) [0x7fe6e5a9e388]
    /usr/lib64/libgtksourceview-2.0.so.0 [0x3c09e2690e]
    /usr/lib64/libgtksourceview-2.0.so.0 [0x3c09e24c98]
    /usr/lib64/libgtksourceview-2.0.so.0(gtk_source_style_scheme_manager_get_scheme+0x65) [0x3c09e24fa5]
    gedit [0x431f57]
    /lib64/libgobject-2.0.so.0(g_type_create_instance+0x137) [0x3c06e2baa7]
    /lib64/libgobject-2.0.so.0 [0x3c06e10a0c]
    /usr/lib64/libgtksourceview-2.0.so.0 [0x3c09e10127]
    /lib64/libgobject-2.0.so.0(g_object_newv+0x291) [0x3c06e11a01]
    /lib64/libgobject-2.0.so.0(g_object_new_valist+0x345) [0x3c06e12555]
    ./gobject-memtrace.so(g_object_new+0xd6) [0x7fe6e5a9e372]
    gedit(gedit_document_new+0x32) [0x430d22]
    gedit [0x4436fa]
    /lib64/libgobject-2.0.so.0(g_type_create_instance+0x137) [0x3c06e2baa7]
    /lib64/libgobject-2.0.so.0 [0x3c06e10a0c]
    /lib64/libgobject-2.0.so.0(g_object_newv+0x291) [0x3c06e11a01]
    /lib64/libgobject-2.0.so.0(g_object_new_valist+0x345) [0x3c06e12555]
    ./gobject-memtrace.so(g_object_new+0xd6) [0x7fe6e5a9e372]
    gedit(_gedit_tab_new+0x1a) [0x442f8a]
    gedit(gedit_window_create_tab+0x7d) [0x44e07d]
    gedit(main+0x55e) [0x4284de]
    /lib64/libc.so.6(__libc_start_main+0xfd) [0x3fa721ea2d]
    gedit [0x427849]
  Stack: 194 hits
    ./gobject-memtrace.so [0x7fe6e5a9e171]
    ./gobject-memtrace.so(g_object_new+0xec) [0x7fe6e5a9e388]
    /usr/lib64/libgtksourceview-2.0.so.0 [0x3c09e2690e]
    /usr/lib64/libgtksourceview-2.0.so.0 [0x3c09e24c98]
    /usr/lib64/libgtksourceview-2.0.so.0(gtk_source_style_scheme_manager_get_scheme+0x65) [0x3c09e24fa5]
    /usr/lib64/libgtksourceview-2.0.so.0 [0x3c09e10992]
    /lib64/libgobject-2.0.so.0(g_type_create_instance+0xe8) [0x3c06e2ba58]
    /lib64/libgobject-2.0.so.0 [0x3c06e10a0c]
    /usr/lib64/libgtksourceview-2.0.so.0 [0x3c09e10127]
    /lib64/libgobject-2.0.so.0(g_object_newv+0x291) [0x3c06e11a01]
    /lib64/libgobject-2.0.so.0(g_object_new_valist+0x345) [0x3c06e12555]
    ./gobject-memtrace.so(g_object_new+0xd6) [0x7fe6e5a9e372]
    gedit(gedit_document_new+0x32) [0x430d22]
    gedit [0x4436fa]
    /lib64/libgobject-2.0.so.0(g_type_create_instance+0x137) [0x3c06e2baa7]
    /lib64/libgobject-2.0.so.0 [0x3c06e10a0c]
    /lib64/libgobject-2.0.so.0(g_object_newv+0x291) [0x3c06e11a01]
    /lib64/libgobject-2.0.so.0(g_object_new_valist+0x345) [0x3c06e12555]
    ./gobject-memtrace.so(g_object_new+0xd6) [0x7fe6e5a9e372]
    gedit(_gedit_tab_new+0x1a) [0x442f8a]
    gedit(gedit_window_create_tab+0x7d) [0x44e07d]
    gedit(main+0x55e) [0x4284de]
    /lib64/libc.so.6(__libc_start_main+0xfd) [0x3fa721ea2d]
    gedit [0x427849]
  Stack: 21 hits
    ./gobject-memtrace.so [0x7fe6e5a9e171]
    ./gobject-memtrace.so(g_object_new+0xec) [0x7fe6e5a9e388]
    /usr/lib64/libgtksourceview-2.0.so.0(gtk_source_style_copy+0x1e) [0x3c09e23f5e]
    /usr/lib64/libgtksourceview-2.0.so.0(gtk_source_style_scheme_get_style+0x131) [0x3c09e25ec1]
    /usr/lib64/libgtksourceview-2.0.so.0 [0x3c09e26479]
    /usr/lib64/libgtksourceview-2.0.so.0 [0x3c09e24c98]
    /usr/lib64/libgtksourceview-2.0.so.0(gtk_source_style_scheme_manager_get_scheme+0x65) [0x3c09e24fa5]
    gedit [0x431f57]
    /lib64/libgobject-2.0.so.0(g_type_create_instance+0x137) [0x3c06e2baa7]
    /lib64/libgobject-2.0.so.0 [0x3c06e10a0c]
    /usr/lib64/libgtksourceview-2.0.so.0 [0x3c09e10127]
    /lib64/libgobject-2.0.so.0(g_object_newv+0x291) [0x3c06e11a01]
    /lib64/libgobject-2.0.so.0(g_object_new_valist+0x345) [0x3c06e12555]
    ./gobject-memtrace.so(g_object_new+0xd6) [0x7fe6e5a9e372]
    gedit(gedit_document_new+0x32) [0x430d22]
    gedit [0x4436fa]
    /lib64/libgobject-2.0.so.0(g_type_create_instance+0x137) [0x3c06e2baa7]
    /lib64/libgobject-2.0.so.0 [0x3c06e10a0c]
    /lib64/libgobject-2.0.so.0(g_object_newv+0x291) [0x3c06e11a01]
    /lib64/libgobject-2.0.so.0(g_object_new_valist+0x345) [0x3c06e12555]
    ./gobject-memtrace.so(g_object_new+0xd6) [0x7fe6e5a9e372]
    gedit(_gedit_tab_new+0x1a) [0x442f8a]
    gedit(gedit_window_create_tab+0x7d) [0x44e07d]
    gedit(main+0x55e) [0x4284de]
    /lib64/libc.so.6(__libc_start_main+0xfd) [0x3fa721ea2d]
    gedit [0x427849]

GdkWindow | created 39 | destroyed 0
  (23 stack traces below threshold 20 omitted)

GtkCheckMenuItem | created 78 | destroyed 77
  Stack: 67 hits
    ./gobject-memtrace.so [0x7fe6e5a9e171]
    ./gobject-memtrace.so(g_object_new+0xec) [0x7fe6e5a9e388]
    /usr/lib64/libgtk-x11-2.0.so.0(gtk_action_create_menu_item+0x7c) [0x3c08e7034c]
    /usr/lib64/libgtk-x11-2.0.so.0 [0x3c09061151]
    /usr/lib64/libgtk-x11-2.0.so.0 [0x3c0905fead]
    /usr/lib64/libgtk-x11-2.0.so.0 [0x3c0905fead]
    /usr/lib64/libgtk-x11-2.0.so.0 [0x3c0905fead]
    /usr/lib64/libgtk-x11-2.0.so.0 [0x3c0905fead]
    /usr/lib64/libgtk-x11-2.0.so.0 [0x3c0905fead]
    /usr/lib64/libgtk-x11-2.0.so.0 [0x3c0905fead]
    /usr/lib64/libgtk-x11-2.0.so.0(gtk_ui_manager_ensure_update+0x31) [0x3c090611e1]
    /usr/lib64/libgtk-x11-2.0.so.0 [0x3c09063ca9]
    gedit [0x450349]
    gedit [0x45119a]
    /lib64/libgobject-2.0.so.0(g_type_create_instance+0x137) [0x3c06e2baa7]
    /lib64/libgobject-2.0.so.0 [0x3c06e10a0c]
    /lib64/libgobject-2.0.so.0(g_object_newv+0x291) [0x3c06e11a01]
    /lib64/libgobject-2.0.so.0(g_object_new_valist+0x345) [0x3c06e12555]
    ./gobject-memtrace.so(g_object_new+0xd6) [0x7fe6e5a9e372]
    gedit [0x429661]
    gedit(gedit_app_create_window+0x1d) [0x42992d]
    gedit(main+0x379) [0x4282f9]
    /lib64/libc.so.6(__libc_start_main+0xfd) [0x3fa721ea2d]
    gedit [0x427849]
  (5 stack traces below threshold 20 omitted)
Comment 41 Sven Herzberg 2010-02-02 14:30:44 UTC
(In reply to comment #37)
> (In reply to comment #36)
> > Colin, did you mean to up the importance of the bug?
> 
> I accidentally hit the "bad_stacktrace" button and that had all sorts of weird
> effects.

Resetting the priority to "Normal" then.
Comment 42 Tim Janik 2010-04-06 10:03:05 UTC
(In reply to comment #32)
> Hmm, if it's going into GLib, I dont' think it should be a preload. LD_PRELOAD
> is inherently unreliable (especially with hiding of symbols from the PLT, etc)
> and specific to particular platforms.

> A separate wrapper program that sets an enviroment variable (maybe pointing to
> an extra FD to avoid overloading stdout) collects the backtraces and saves them
> nicely formatted might still make sense.

I have to agree with Owen here, LD_PRELOAD is quite fragile. I'd rather see something like support for a debugging file descriptor, e.g. G_DEBUG_INFO_FD which produces machine parsable debugging information *and* uses and extensible format for any future debugging info we might come up with. SO we could use, e.g.:
  G_DEBUG_INFO_FD=122 SomeGLibProgram 122>debug.info
  glibdebuganalyze debug.info
Comment 43 Colin Walters 2010-04-06 11:42:53 UTC
As far as I'm concerned this type of thing is obsoleted by

https://bugzilla.gnome.org/show_bug.cgi?id=606044

So I won't be updating my patch.
Comment 44 David Woodhouse 2010-09-24 13:14:41 UTC
I'm sure that's really sexy, but there are command lines and sample output here for mbarnes' stuff, while I have no idea at all how to use the stuff in bug 606044. Is there documentation anywhere? All I want is the simple stats that Matt's patch gave us...
Comment 45 Matthew Barnes 2011-03-09 22:11:04 UTC
Created attachment 183030 [details] [review]
Original patch, updated for GLib 2.28

I know this is never going to land because the systemtap way is better, but I still find my original patch simple and useful when I want a quick overview of how badly object references are leaking.  So as a public service here's an updated patch for GLib 2.28.

To use:

  1. GOBJECT_DEBUG=types $MY_APPLICATION 2>&1 | gobject-stats
  2. Do stuff in your app, then quit.
  3. Read the GType stats.
Comment 46 Matthew Barnes 2011-03-09 22:31:28 UTC
Created attachment 183031 [details] [review]
Enhanced patch for GLib 2.28

Actually, long as I'm hacking on this again, here's an enhanced version that adds a "# Leaked" column to the gobject-stats output and sorts on it by default in descending order.
Comment 47 Colin Walters 2011-03-16 14:06:51 UTC
See https://bugzilla.gnome.org/show_bug.cgi?id=614619 for a sample script using SystemTap on glib, GObject, and gjs.
Comment 48 Colin Walters 2011-03-16 14:54:58 UTC
Created attachment 183544 [details]
glib memtrace systemtap script
Comment 49 Colin Walters 2011-03-16 15:19:31 UTC
So in the big picture, I think it's worth considering having a separate --enable-deveoper-mode mode for GLib which changes a bunch of things (e.g. turns off -Bsymbolic so you can LD_PRELOAD, and enables more assertions, etc.)  Think of this as moving GLib a bit more towards "kernel style" where you can recompile with things like lockdep.

However, we should still have a hard set of defaults that we expect OS builders to use.  Practically speaking in a "distro" then the above might manifest as a glib2-debugging package which had a separate .so.

In that scenario it would then sense to me to land something like Matt's patch in --enable-developer-mode.
Comment 50 Benjamin Otte (Company) 2011-03-16 16:19:49 UTC
(In reply to comment #49)
> So in the big picture, I think it's worth considering having a separate
> --enable-deveoper-mode mode for GLib which changes a bunch of things.
>
The only thing that leads to is frustration. For two reasons:
1) People cannot run the script you gave them because their computer doesn't have the developer mode version available.
2) People cannot reproduce bugs because they only manifest in one of the versions.

So I'm very strongly in favor of not doing something like this.
Comment 51 Matthew Barnes 2012-06-24 18:13:35 UTC
Created attachment 217133 [details] [review]
Updated patch for GLib 2.33

Had occasion to use this again.  It helped me easily spot a huge memory leak in Camel.

Here's an updated patch for those who may still find this useful.  Applies against the latest git revision (GLib 2.33.2).
Comment 52 Owen Taylor 2014-10-09 21:05:51 UTC
Created attachment 288174 [details] [review]
Add simple instance count facility

Here's a quick patch along the same lines I've been using for some gnome-shell
leak detection. There's no collection, reporting, max, total, etc here - 
just a count of currently live objects available as g_type_get_instance_count().

From the GNOME Shell perspective, what I wanted to be able to do do was have
a hot key that:

 - garbage collected
 - dumped the current counts to a file

The differential between the counts before and after an activity reveals leaks.

As an implementation technique I put the counts right in the GTypeNode; it would
be also possible to put a pointer in the GTypeNode to a block if we were keeping
more sophisticated stats.

Having the statistics available at the app level definitely allows for
interesting possibilities and should be part of anything like this that is landed;
it's also something that you *can't* at all easily do with systemtap. Other
questions/thoughts that come to mind examining the bug history:

 * Can we do something cheap enough to be always on? It would definitely be cool
   if I could ask someone using GNOME Shell who has a bunch of memory allocated to
   go to the looking glass console and see what sort of objects are allocated without
   a need to restart in a special mode.

 * How useful are the high-water-mark and total-instances-allocated stats compared
   to the live object stats?

 * It definitely seems to me like that shouldn't be dependent on --enable-debug - 
   at most a runtime switch - a few well-predicted branches per type instance creation
   and freeing will have almost no effect, and having a useful facility for app-authors
   out of the box would be very appreciated.
Comment 53 Matthew Barnes 2014-10-09 21:41:54 UTC
(In reply to comment #52)
>  * How useful are the high-water-mark and total-instances-allocated stats
>    compared to the live object stats?

I vaguely recall at the time I suggested this I was trying to track the source of sporadic CPU or memory usage spikes in Evolution where objects were being created and destroyed very rapidly.  The postmortem stats did help on rare occasions, but I don't know if it's worth keeping.
Comment 54 Matthias Clasen 2014-10-09 22:35:13 UTC
(In reply to comment #52)
> Created an attachment (id=288174) [details] [review]
> Add simple instance count facility
> 
> Here's a quick patch along the same lines I've been using for some gnome-shell
> leak detection. There's no collection, reporting, max, total, etc here - 
> just a count of currently live objects available as
> g_type_get_instance_count().
> 
> From the GNOME Shell perspective, what I wanted to be able to do do was have
> a hot key that:
> 
>  - garbage collected
>  - dumped the current counts to a file
> 
> The differential between the counts before and after an activity reveals leaks.
> 
> As an implementation technique I put the counts right in the GTypeNode; it
> would
> be also possible to put a pointer in the GTypeNode to a block if we were
> keeping
> more sophisticated stats.
> 
> Having the statistics available at the app level definitely allows for
> interesting possibilities and should be part of anything like this that is
> landed;
> it's also something that you *can't* at all easily do with systemtap. Other
> questions/thoughts that come to mind examining the bug history:
> 
>  * Can we do something cheap enough to be always on? It would definitely be
> cool
>    if I could ask someone using GNOME Shell who has a bunch of memory allocated
> to
>    go to the looking glass console and see what sort of objects are allocated
> without
>    a need to restart in a special mode.

I would love to have something like this available in GtkInspector too.
Comment 55 Matthias Clasen 2014-10-09 22:44:47 UTC
Review of attachment 288174 [details] [review]:

::: gobject/gtype.c
@@ +3836,3 @@
+ *
+ * Returns: the number of instances allocated of the given type;
+ *  if the debug flag is not set or the instance is not instantiable,

s/instance/type/ here

@@ +4379,3 @@
       GDebugKey debug_keys[] = {
         { "objects", G_TYPE_DEBUG_OBJECTS },
+        { "instance_count", G_TYPE_DEBUG_INSTANCE_COUNT },

For the inspector, this would be much more useful if it could be on by default. We can still show the information of course, if the environment variable happens to be set.
Comment 56 Matthias Clasen 2014-10-10 01:41:33 UTC
Review of attachment 288174 [details] [review]:

::: gobject/gtype.c
@@ +3847,3 @@
+  g_return_if_fail (node != NULL);
+
+  return g_atomic_int_get (&node->instance_count);

This needs an ifdef
Comment 57 Matthias Clasen 2014-10-10 03:38:11 UTC
An inspector patch using this is in bug 738272
Comment 58 Matthias Clasen 2014-10-10 10:34:41 UTC
Review of attachment 288174 [details] [review]:

::: gobject/gtype.c
@@ +229,3 @@
+#ifdef G_ENABLE_DEBUG
+  guint volatile instance_count;
+#endif

Would be nice to have a static assertion that this doesn't affect struct layout, but just fills a hole.

Also, once we have asserted that, we could just do away with the ifdef here ?
Comment 59 David Woodhouse 2014-10-10 11:12:46 UTC
(In reply to comment #58)
> Would be nice to have a static assertion that this doesn't affect struct
> layout, but just fills a hole.

It only fills a hole on 64-bit architectures. On 32-bit it does affect struct layout.
Comment 60 Matthias Clasen 2014-10-10 16:33:57 UTC
(In reply to comment #59)
> (In reply to comment #58)
> > Would be nice to have a static assertion that this doesn't affect struct
> > layout, but just fills a hole.
> 
> It only fills a hole on 64-bit architectures. On 32-bit it does affect struct
> layout.

I guess one answer would be to only do it on 64-bit, then.
Comment 61 Matthias Clasen 2014-10-10 19:15:53 UTC
Created attachment 288254 [details] [review]
Add simple instance count facility

Add GOBJECT_DEBUG=instance_count which enables internal accounting
of the number of instances of each GType, and g_type_get_instance_count()
to retrieve the result. We only support this on architectures where
we can fit an integer into the type node struct without changing ABI.
Comment 62 Matthias Clasen 2014-10-10 19:16:32 UTC
Here is an iteration of Owens patch that adds a missing ifdef and restricts the functionality to x86-64.
Comment 63 Matthias Clasen 2014-10-10 19:20:46 UTC
Created attachment 288255 [details] [review]
Make instance counting unconditional

The overhead for maintaining this instance counter should
be small, and there is value in being able to always get
instance counts without having to restart the application.
Comment 64 Matthias Clasen 2014-10-11 17:56:30 UTC
I ended up going with Owens original patch, mostly. ABI is not actually
a concern for type nodes; they are purely internal. And I've kept the
runtime flag in place; if we convince ourselves that performance is not
affected, we can drop it later.
Attachment 288254 [details] pushed as 011bf87 - Add simple instance count facility