Dispatch of GObject virtual functions in GtkMM



Hi,

I've been doing some benchmarking of basic little illustrative
programs which record and print the time required to instantiate
widget hierarchies of varying nesting depths. I write these programs
first in regular Gtk+ and then with Gtkmm.

I consistently find that the time required to instantiate and add
widgets into their parents is on the order of twice as expensive when
done with Gtkmm. Is there significant overhead in the dispatch of
GObject virtual functions? Am I right in visualizing the dispatch like
this:

 * the thin custom GObject subclass of a label gets requested to expose
 * the wrapper class tunnels this request out to overrideable virtual
method on the C++ object
 * the default implementation of the C++ method calls back down to
the underlying GtkLabel C implementation

?

I'm attaching an example programs which sort of illustrates this.
#include <gtk/gtkbox.h>
#include <gtk/gtkbutton.h>
#include <gtk/gtkcheckbutton.h>
#include <gtk/gtkmain.h>
#include <gtk/gtktable.h>
#include <gtk/gtkwindow.h>

#include <sys/time.h>

#define ROWS    5
#define COLUMNS 5

static GtkWidget *
create_table_item (guint index)
{
    GtkWidget * item = NULL;
    gchar * label = g_strdup_printf ("%d", index);

    item = gtk_vbox_new (FALSE, 0);

    GtkWidget * top = gtk_hbox_new (FALSE, 0);
    GtkWidget * bottom = gtk_hbox_new (FALSE, 0);

    gtk_container_add (GTK_CONTAINER (item), top);
    gtk_container_add (GTK_CONTAINER (item), bottom);

    gtk_container_add (GTK_CONTAINER (top),
                       gtk_button_new_with_label (label));
    gtk_container_add (GTK_CONTAINER (top),
                       gtk_alignment_new (0.5, 0.5, 0.0, 0.0));
    gtk_container_add (GTK_CONTAINER (bottom),
                       gtk_label_new (""));
    gtk_container_add (GTK_CONTAINER (bottom),
                       gtk_check_button_new ());

    g_free (label);
    return item;
}

static gboolean
window_expose_cb (GtkWindow * win, GdkEventExpose * e)
{
    gtk_main_quit ();
    return FALSE;
}

int
main (int argc, char * argv[])
{
    struct timeval t;
    guint i, j;

    gettimeofday (&t, NULL);
    printf ("%03d.%03d: main gets control\n",
            (int) (t.tv_sec % 1000),
            (int) (t.tv_usec / 1000));

    gtk_init (&argc, &argv);

    GtkWidget * window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    GtkWidget * table = gtk_table_new (ROWS, COLUMNS, FALSE);

    for (i = 0; i < ROWS; i++)
    {
        for (j = 0; j < COLUMNS; j++)
        {
            GtkWidget * item = create_table_item (i * COLUMNS + j);
            gtk_table_attach_defaults (GTK_TABLE (table),
                                       item,
                                       j,
                                       j + 1,
                                       i,
                                       i + 1);

        }
    }

    gtk_container_add (GTK_CONTAINER (window), table);
    gtk_widget_show_all (window);

    g_signal_connect (G_OBJECT (window), "expose-event",
                      G_CALLBACK (window_expose_cb), NULL);

    gtk_main ();
    return 0;
}
#include <gtkmm/alignment.h>
#include <gtkmm/box.h>
#include <gtkmm/button.h>
#include <gtkmm/checkbutton.h>
#include <gtkmm/label.h>
#include <gtkmm/main.h>
#include <gtkmm/table.h>
#include <gtkmm/window.h>

#include <sys/time.h>

#define ROWS    5
#define COLUMNS 5

using namespace Gtk;

class window : public Window
{
    public:
        window()
            : Window (WINDOW_TOPLEVEL)
        {
        }

    protected:
        virtual bool on_expose_event (GdkEventExpose* e)
        {
            Main::quit ();
            return Window::on_expose_event (e);
        }
};

static Widget*
create_table_item (unsigned int index)
{
    gchar * label = g_strdup_printf ("%d", index);

    VBox * item = new VBox (false, 0);
    HBox * top = new HBox (false, 0);
    HBox * bottom = new HBox (false, 0);

    item->add (*manage (top));
    item->add (*manage (bottom));

    top->add (*manage (new Button (label)));
    top->add (*manage (new Alignment (0.5, 0.5, 0.0, 0.0)));
    bottom->add (*manage (new Label ("")));
    bottom->add (*manage (new CheckButton ("")));

    g_free (label);
    return item;
}

int
main (int argc, char * argv[])
{
    struct timeval t;

    gettimeofday (&t, NULL);
    printf ("%d.%d: main gets control\n",
            (int) (t.tv_sec % 1000),
            (int) (t.tv_usec / 1000));

    Main loop (argc, argv);

    window w;
    Table table (ROWS, COLUMNS, false);

    for (unsigned i = 0; i < ROWS; i++)
    {
        for (unsigned j = 0; j < COLUMNS; j++)
        {
            Widget* item = create_table_item (i * COLUMNS + j);
            Gtk::manage (item);

            table.attach (*item, j, j + 1, i, i + 1);
        }
    }

    w.add (table);
    w.show_all ();

    loop.run ();
    return 0;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]