perf: Delete

The perf/ directory was unused and the code was outdated. So it's easier
to delete than trying to modernize the code.
This commit is contained in:
Benjamin Otte 2013-07-08 16:17:46 +02:00
parent 6449b4a610
commit 41010d15b3
11 changed files with 0 additions and 1358 deletions

View File

@ -1,80 +0,0 @@
## Makefile.am for gtk+/perf
include $(top_srcdir)/Makefile.decl
AM_CPPFLAGS = \
-I$(top_srcdir) \
-I$(top_builddir)/gdk \
-I$(top_srcdir)/gdk \
-DGDK_DISABLE_DEPRECATED \
-DGTK_DISABLE_DEPRECATED \
$(GTK_DEBUG_FLAGS) \
$(GTK_DEP_CFLAGS)
DEPS = \
$(top_builddir)/gtk/libgtk-3.la
LDADDS = \
$(top_builddir)/gtk/libgtk-3.la \
$(top_builddir)/gdk/libgdk-3.la \
$(GTK_DEP_LIBS)
noinst_PROGRAMS = \
testperf
testperf_DEPENDENCIES = $(TEST_DEPS)
testperf_LDADD = $(LDADDS)
testperf_SOURCES = \
appwindow.c \
gtkwidgetprofiler.c \
gtkwidgetprofiler.h \
main.c \
textview.c \
treeview.c \
typebuiltins.c \
typebuiltins.h \
widgets.h
BUILT_SOURCES = \
typebuiltins.c \
typebuiltins.h
stamp_files = \
stamp-typebuiltins.h
headers_with_enums = \
gtkwidgetprofiler.h
MAINTAINERCLEANFILES = $(BUILT_SOURCES) $(stamp_files)
typebuiltins.h: stamp-typebuiltins.h
@true
stamp-typebuiltins.h: $(headers_with_enums) typebuiltins.h.template
( cd $(srcdir) && $(GLIB_MKENUMS) --template typebuiltins.h.template \
$(headers_with_enums) ) >> xgen-gtbh \
&& (cmp -s xgen-gtbh typebuiltins.h || cp xgen-gtbh typebuiltins.h ) \
&& rm -f xgen-gtbh \
&& echo timestamp > $(@F)
typebuiltins.c: $(headers_with_enums) typebuiltins.c.template
( cd $(srcdir) && $(GLIB_MKENUMS) --template typebuiltins.c.template \
$(headers_with_enums) ) > xgen-gtbc \
&& cp xgen-gtbc typebuiltins.c \
&& rm -f xgen-gtbc
EXTRA_DIST += \
README \
typebuiltins.c.template \
typebuiltins.h.template \
$(BUILT_SOURCES)
# if srcdir!=builddir, clean out maintainer-clean files from builddir
# this allows dist to pass.
distclean-local:
if test $(srcdir) != .; then \
rm -f $(MAINTAINERCLEANFILES); \
fi
-include $(top_srcdir)/git.mk

View File

@ -1,220 +0,0 @@
README for gtk+/perf
--------------------
This is a framework for testing performance in GTK+. For GTK+, being
performant does not only mean "paint widgets fast". It also means
things like the time needed to set up widgets, to map and draw a
window for the first time, and emitting/propagating signals.
The following is accurate as of 2006/Jun/14.
Background
----------
A widget's lifetime looks more or less like this:
1. Instantiation
2. Size request
3. Size allocate
5. Realize
4. Map
5. Expose
6. Destroy
Some of these stages are particularly interesting:
- Instantiation means creating the widget. This may be as simple as a
few malloc()s and setting some fields. It could also be a
complicated operation if the widget needs to contact an external
server to create itself, or if it needs to read data files.
- Size requisition is when GTK+ asks the widget, "how big do you want
to be on the screen"? This can be an expensive operation. The
widget has to measure its text, measure its icons (and thus load its
icons), and generally run through its internal layout code.
- Realization is when the widget creates its GDK resources, like its
GdkWindow and graphics contexts it may need. This could be
expensive if the widget needs to load data files for cursors or
backgrounds.
- Expose is when the widget gets repainted. This will happen many
times throughout the lifetime of the widget: every time you drag a
window on top of it, every time its data changes and it needs to
redraw, every time it gets resized.
GtkWidgetProfiler is a mechanism to let you get individual timings for
each of the stages in the lifetime of a widget. It also lets you run
some stages many times in a sequence, so that you can run a real
profiler and get an adequate number of samples. For example,
GtkWidgetProfiler lets you say "repaint this widget 1000 times".
Why is this not as simple as doing
start_timer ();
for (i = 0; i < 1000; i++) {
gtk_widget_queue_draw (widget);
while (gtk_events_pending ())
gtk_main_iteration ();
}
stop_timer ();
Huh?
Because X is an asynchronous window system. So, when you send the
"paint" commands, your program will regain control but it will take
some time for the X server to actually process those commands.
GtkWidgetProfiler has special code to wait for the X server and give
you accurate timings.
Using the framework
-------------------
Right now the framework is very simple; it just has utility functions
to time widget creation, mapping, exposure, and destruction. To run
such a test, you use the GtkWidgetProfiler object in
gtkwidgetprofiler.h.
The gtk_widget_profiler_profile_boot() function will emit the
"create-widget" signal so that you can create your widget for
testing. It will then take timings for the widget, and emit the
"report" signal as appropriate.
The "create-widget" signal:
The handler has this form:
GtkWidget *create_widget_callback (GtkWidgetProfiler *profiler,
gpointer user_data);
You need to create a widget in your handler, and return it. Do not
show the widget; the profiler will do that by itself at the right
time, and will actually complain if you show the widget.
The "report" signal:
This function will get called when the profiler wants to report that
it finished timing an important stage in the lifecycle of your
widget. The handler has this form:
void report_callback (GtkWidgetProfiler *profiler,
GtkWidgetProfilerReport report,
GtkWidget *widget,
gdouble elapsed,
gpointer user_data);
The "report" argument tells you what happened to your widget:
GTK_WIDGET_PROFILER_REPORT_CREATE. A timer gets started right
before the profiler emits the "create-widget" signal,, and it gets
stopped when your callback returns with the new widget. This
measures the time it takes to set up your widget, but not show it.
GTK_WIDGET_PROFILER_REPORT_MAP. A timer gets started right before
the profiler calls gtk_widget_show_all() on your widget, and it
gets stopped when the the widget has been mapped.
GTK_WIDGET_PROFILER_REPORT_EXPOSE. A timer gets started right before
the profiler starts waiting for GTK+ and the X server to finish
painting your widget, and it gets stopped when the widget is fully
painted to the screen.
GTK_WIDGET_PROFILER_REPORT_DESTROY. A timer gets started right
before the profiler calls gtk_widget_destroy() on your widget, and
it gets stopped when gtk_widget_destroy() returns.
As a very basic example of using GtkWidgetProfiler is this:
----------------------------------------------------------------------
#include <stdio.h>
#include <gtk/gtk.h>
#include "gtkwidgetprofiler.h"
static GtkWidget *
create_widget_cb (GtkWidgetProfiler *profiler, gpointer data)
{
GtkWidget *window;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
/* ... fill the window with widgets, and don't show them ... */
return window;
}
static void
report_cb (GtkWidgetProfiler *profiler, GtkWidgetProfilerReport report, GtkWidget *widget, gdouble elapsed, gpointer data)
{
const char *type;
switch (report) {
case GTK_WIDGET_PROFILER_REPORT_CREATE:
type = "widget creation";
break;
case GTK_WIDGET_PROFILER_REPORT_MAP:
type = "widget map";
break;
case GTK_WIDGET_PROFILER_REPORT_EXPOSE:
type = "widget expose";
break;
case GTK_WIDGET_PROFILER_REPORT_DESTROY:
type = "widget destruction";
break;
default:
g_assert_not_reached ();
type = NULL;
}
fprintf (stderr, "%s: %g sec\n", type, elapsed);
if (report == GTK_WIDGET_PROFILER_REPORT_DESTROY)
fputs ("\n", stderr);
}
int
main (int argc, char **argv)
{
GtkWidgetProfiler *profiler;
gtk_init (&argc, &argv);
profiler = gtk_widget_profiler_new ();
g_signal_connect (profiler, "create-widget",
G_CALLBACK (create_widget_cb), NULL);
g_signal_connect (profiler, "report",
G_CALLBACK (report_cb), NULL);
gtk_widget_profiler_set_num_iterations (profiler, 100);
gtk_widget_profiler_profile_boot (profiler);
gtk_widget_profiler_profile_expose (profiler);
return 0;
}
----------------------------------------------------------------------
Getting meaningful results
--------------------------
Getting times for widget creation/mapping/exposing/destruction is
interesting, but how do you actually find the places that need
optimizing?
Why, you run the tests under a profiler, of course.
FIXME: document how to do this.
Feedback
--------
Please mail your feedback to Federico Mena-Quintero <federico@novell.com>.
This performance framework is a work in progress.

View File

@ -1,233 +0,0 @@
/* This file contains utility functions to create what would be a typical "main
* window" for an application.
*
* TODO:
*
* Measurements happen from the start of the destruction of the last window. Use
* GTimer rather than X timestamps to fix this (it uses gettimeofday() internally!)
*
* Make non-interactive as well by using the above.
*
*/
#include <string.h>
#include <gtk/gtk.h>
#include "widgets.h"
static void
quit_cb (GtkWidget *widget, gpointer data)
{
gtk_main_quit ();
}
static void
noop_cb (GtkWidget *widget, gpointer data)
{
/* nothing */
}
static const GtkActionEntry menu_action_entries[] = {
{ "FileMenu", NULL, "_File" },
{ "EditMenu", NULL, "_Edit" },
{ "ViewMenu", NULL, "_View" },
{ "HelpMenu", NULL, "_Help" },
{ "New", GTK_STOCK_NEW, "_New", "<control>N", "Create a new document", G_CALLBACK (noop_cb) },
{ "Open", GTK_STOCK_OPEN, "_Open", "<control>O", "Open a file", G_CALLBACK (noop_cb) },
{ "Save", GTK_STOCK_SAVE, "_Save", "<control>S", "Save the document", G_CALLBACK (noop_cb) },
{ "SaveAs", GTK_STOCK_SAVE_AS, "Save _As...", NULL, "Save the document with a different name", NULL},
{ "PrintPreview", GTK_STOCK_PRINT_PREVIEW, "Print Previe_w", NULL, "See how the document will be printed", G_CALLBACK (noop_cb) },
{ "Print", GTK_STOCK_PRINT, "_Print", "<control>P", "Print the document", G_CALLBACK (noop_cb) },
{ "Close", GTK_STOCK_CLOSE, "_Close", "<control>W", "Close the document", G_CALLBACK (noop_cb) },
{ "Quit", GTK_STOCK_QUIT, "_Quit", "<control>Q", "Quit the program", G_CALLBACK (quit_cb) },
{ "Undo", GTK_STOCK_UNDO, "_Undo", "<control>Z", "Undo the last action", G_CALLBACK (noop_cb) },
{ "Redo", GTK_STOCK_REDO, "_Redo", "<control>Y", "Redo the last action", G_CALLBACK (noop_cb) },
{ "Cut", GTK_STOCK_CUT, "Cu_t", "<control>X", "Cut the selection to the clipboard", G_CALLBACK (noop_cb) },
{ "Copy", GTK_STOCK_COPY, "_Copy", "<control>C", "Copy the selection to the clipboard", G_CALLBACK (noop_cb) },
{ "Paste", GTK_STOCK_PASTE, "_Paste", "<control>V", "Paste the contents of the clipboard", G_CALLBACK (noop_cb) },
{ "Delete", GTK_STOCK_DELETE, "_Delete", "Delete", "Delete the selection", G_CALLBACK (noop_cb) },
{ "SelectAll", NULL, "Select _All", "<control>A", "Select the whole document", G_CALLBACK (noop_cb) },
{ "Preferences", GTK_STOCK_PREFERENCES, "Pr_eferences", NULL, "Configure the application", G_CALLBACK (noop_cb) },
{ "ZoomFit", GTK_STOCK_ZOOM_FIT, "Zoom to _Fit", NULL, "Zoom the document to fit the window", G_CALLBACK (noop_cb) },
{ "Zoom100", GTK_STOCK_ZOOM_100, "Zoom _1:1", NULL, "Zoom to 1:1 scale", G_CALLBACK (noop_cb) },
{ "ZoomIn", GTK_STOCK_ZOOM_IN, "Zoom _In", NULL, "Zoom into the document", G_CALLBACK (noop_cb) },
{ "ZoomOut", GTK_STOCK_ZOOM_OUT, "Zoom _Out", NULL, "Zoom away from the document", G_CALLBACK (noop_cb) },
{ "FullScreen", GTK_STOCK_FULLSCREEN, "Full _Screen", "F11", "Use the whole screen to view the document", G_CALLBACK (noop_cb) },
{ "HelpContents", GTK_STOCK_HELP, "_Contents", "F1", "Show the table of contents for the help system", G_CALLBACK (noop_cb) },
{ "About", GTK_STOCK_ABOUT, "_About", NULL, "About this application", G_CALLBACK (noop_cb) }
};
static const char ui_description[] =
"<ui>"
" <menubar name=\"MainMenu\">"
" <menu action=\"FileMenu\">"
" <menuitem action=\"New\"/>"
" <menuitem action=\"Open\"/>"
" <menuitem action=\"Save\"/>"
" <menuitem action=\"SaveAs\"/>"
" <separator/>"
" <menuitem action=\"PrintPreview\"/>"
" <menuitem action=\"Print\"/>"
" <separator/>"
" <menuitem action=\"Close\"/>"
" <menuitem action=\"Quit\"/>"
" </menu>"
" <menu action=\"EditMenu\">"
" <menuitem action=\"Undo\"/>"
" <menuitem action=\"Redo\"/>"
" <separator/>"
" <menuitem action=\"Cut\"/>"
" <menuitem action=\"Copy\"/>"
" <menuitem action=\"Paste\"/>"
" <menuitem action=\"Delete\"/>"
" <separator/>"
" <menuitem action=\"SelectAll\"/>"
" <separator/>"
" <menuitem action=\"Preferences\"/>"
" </menu>"
" <menu action=\"ViewMenu\">"
" <menuitem action=\"ZoomFit\"/>"
" <menuitem action=\"Zoom100\"/>"
" <menuitem action=\"ZoomIn\"/>"
" <menuitem action=\"ZoomOut\"/>"
" <separator/>"
" <menuitem action=\"FullScreen\"/>"
" </menu>"
" <menu action=\"HelpMenu\">"
" <menuitem action=\"HelpContents\"/>"
" <menuitem action=\"About\"/>"
" </menu>"
" </menubar>"
" <toolbar name=\"MainToolbar\">"
" <toolitem action=\"New\"/>"
" <toolitem action=\"Open\"/>"
" <toolitem action=\"Save\"/>"
" <separator/>"
" <toolitem action=\"Print\"/>"
" <separator/>"
" <toolitem action=\"Undo\"/>"
" <toolitem action=\"Redo\"/>"
" <separator/>"
" <toolitem action=\"Cut\"/>"
" <toolitem action=\"Copy\"/>"
" <toolitem action=\"Paste\"/>"
" </toolbar>"
"</ui>";
static GtkUIManager *
uimanager_new (void)
{
GtkUIManager *ui;
GtkActionGroup *action_group;
GError *error;
ui = gtk_ui_manager_new ();
action_group = gtk_action_group_new ("Actions");
gtk_action_group_add_actions (action_group, menu_action_entries, G_N_ELEMENTS (menu_action_entries), NULL);
gtk_ui_manager_insert_action_group (ui, action_group, 0);
g_object_unref (action_group);
error = NULL;
if (!gtk_ui_manager_add_ui_from_string (ui, ui_description, -1, &error))
g_error ("Could not parse the uimanager XML: %s", error->message);
return ui;
}
static GtkWidget *
menubar_new (GtkUIManager *ui)
{
return gtk_ui_manager_get_widget (ui, "/MainMenu");
}
static GtkWidget *
toolbar_new (GtkUIManager *ui)
{
return gtk_ui_manager_get_widget (ui, "/MainToolbar");
}
static GtkWidget *
drawing_area_new (void)
{
GtkWidget *darea;
darea = gtk_drawing_area_new ();
gtk_widget_set_size_request (darea, 640, 480);
return darea;
}
static GtkWidget *
content_area_new (void)
{
GtkWidget *notebook;
notebook = gtk_notebook_new ();
gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
drawing_area_new (),
gtk_label_new ("First"));
gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
drawing_area_new (),
gtk_label_new ("Second"));
gtk_notebook_append_page (GTK_NOTEBOOK (notebook),
drawing_area_new (),
gtk_label_new ("Third"));
return notebook;
}
static GtkWidget *
status_bar_new (void)
{
return gtk_statusbar_new ();
}
static gboolean
delete_event_cb (GtkWidget *widget, GdkEvent *event, gpointer data)
{
gtk_main_quit ();
return FALSE;
}
GtkWidget *
appwindow_new (void)
{
GtkWidget *window;
GtkUIManager *ui;
GtkWidget *vbox;
GtkWidget *widget;
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Main window");
g_signal_connect (window, "delete-event",
G_CALLBACK (delete_event_cb), NULL);
ui = uimanager_new ();
g_signal_connect_swapped (window, "destroy",
G_CALLBACK (g_object_unref), ui);
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (window), vbox);
widget = menubar_new (ui);
gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
widget = toolbar_new (ui);
gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
widget = content_area_new ();
gtk_box_pack_start (GTK_BOX (vbox), widget, TRUE, TRUE, 0);
widget = status_bar_new ();
gtk_box_pack_end (GTK_BOX (vbox), widget, FALSE, FALSE, 0);
return window;
}

View File

@ -1,472 +0,0 @@
#include "config.h"
#include <string.h>
#include "gtkwidgetprofiler.h"
#include "typebuiltins.h"
typedef enum {
STATE_NOT_CREATED,
STATE_INSTRUMENTED_NOT_MAPPED,
STATE_INSTRUMENTED_MAPPED
} State;
struct _GtkWidgetProfilerPrivate {
State state;
GtkWidget *profiled_widget;
GtkWidget *toplevel;
int n_iterations;
GTimer *timer;
gulong toplevel_draw_id;
gulong toplevel_property_notify_event_id;
GdkAtom profiler_atom;
guint profiling : 1;
};
G_DEFINE_TYPE (GtkWidgetProfiler, gtk_widget_profiler, G_TYPE_OBJECT);
static void gtk_widget_profiler_finalize (GObject *object);
enum {
CREATE_WIDGET,
REPORT,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
static void
gtk_widget_profiler_class_init (GtkWidgetProfilerClass *class)
{
GObjectClass *object_class;
object_class = (GObjectClass *) class;
signals[CREATE_WIDGET] =
g_signal_new ("create-widget",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkWidgetProfilerClass, create_widget),
NULL, NULL,
NULL,
G_TYPE_OBJECT, 0);
signals[REPORT] =
g_signal_new ("report",
G_OBJECT_CLASS_TYPE (object_class),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GtkWidgetProfilerClass, report),
NULL, NULL,
NULL,
G_TYPE_NONE, 3,
GTK_TYPE_WIDGET_PROFILER_REPORT,
G_TYPE_OBJECT,
G_TYPE_DOUBLE);
object_class->finalize = gtk_widget_profiler_finalize;
}
static void
gtk_widget_profiler_init (GtkWidgetProfiler *profiler)
{
GtkWidgetProfilerPrivate *priv;
priv = g_new0 (GtkWidgetProfilerPrivate, 1);
profiler->priv = priv;
priv->state = STATE_NOT_CREATED;
priv->n_iterations = 1;
priv->timer = g_timer_new ();
priv->profiler_atom = gdk_atom_intern ("GtkWidgetProfiler", FALSE);
}
static void
reset_state (GtkWidgetProfiler *profiler)
{
GtkWidgetProfilerPrivate *priv;
priv = profiler->priv;
if (priv->toplevel)
{
g_signal_handler_disconnect (priv->toplevel, priv->toplevel_draw_id);
priv->toplevel_draw_id = 0;
g_signal_handler_disconnect (priv->toplevel, priv->toplevel_property_notify_event_id);
priv->toplevel_property_notify_event_id = 0;
gtk_widget_destroy (priv->toplevel);
priv->toplevel = NULL;
priv->profiled_widget = NULL;
}
priv->state = STATE_NOT_CREATED;
}
static void
gtk_widget_profiler_finalize (GObject *object)
{
GtkWidgetProfiler *profiler;
GtkWidgetProfilerPrivate *priv;
profiler = GTK_WIDGET_PROFILER (object);
priv = profiler->priv;
reset_state (profiler);
g_timer_destroy (priv->timer);
g_free (priv);
G_OBJECT_CLASS (gtk_widget_profiler_parent_class)->finalize (object);
}
GtkWidgetProfiler *
gtk_widget_profiler_new (void)
{
return g_object_new (GTK_TYPE_WIDGET_PROFILER, NULL);
}
void
gtk_widget_profiler_set_num_iterations (GtkWidgetProfiler *profiler,
gint n_iterations)
{
GtkWidgetProfilerPrivate *priv;
g_return_if_fail (GTK_IS_WIDGET_PROFILER (profiler));
g_return_if_fail (n_iterations > 0);
priv = profiler->priv;
priv->n_iterations = n_iterations;
}
static void
report (GtkWidgetProfiler *profiler,
GtkWidgetProfilerReport report,
gdouble elapsed)
{
GtkWidgetProfilerPrivate *priv;
priv = profiler->priv;
g_signal_emit (profiler, signals[REPORT], 0, report, priv->profiled_widget, elapsed);
}
static GtkWidget *
create_widget_via_emission (GtkWidgetProfiler *profiler)
{
GtkWidget *widget;
widget = NULL;
g_signal_emit (profiler, signals[CREATE_WIDGET], 0, &widget);
if (!widget)
g_error ("The profiler emitted the \"create-widget\" signal but the signal handler returned no widget!");
if (gtk_widget_get_visible (widget) || gtk_widget_get_mapped (widget))
g_error ("The handler for \"create-widget\" must return an unmapped and unshown widget");
return widget;
}
static gboolean
toplevel_property_notify_event_cb (GtkWidget *widget, GdkEventProperty *event, gpointer data)
{
GtkWidgetProfiler *profiler;
GtkWidgetProfilerPrivate *priv;
gdouble elapsed;
profiler = GTK_WIDGET_PROFILER (data);
priv = profiler->priv;
if (event->atom != priv->profiler_atom)
return FALSE;
/* Finish timing map/expose */
elapsed = g_timer_elapsed (priv->timer, NULL);
report (profiler, GTK_WIDGET_PROFILER_REPORT_EXPOSE, elapsed);
gtk_main_quit (); /* This will get us back to the end of profile_map_expose() */
return TRUE;
}
static gboolean
toplevel_idle_after_draw_cb (gpointer data)
{
GtkWidgetProfiler *profiler;
GtkWidgetProfilerPrivate *priv;
profiler = GTK_WIDGET_PROFILER (data);
priv = profiler->priv;
gdk_property_change (gtk_widget_get_window (priv->toplevel),
priv->profiler_atom,
gdk_atom_intern ("STRING", FALSE),
8,
GDK_PROP_MODE_REPLACE,
(guchar *) "hello",
strlen ("hello"));
return FALSE;
}
static gboolean
toplevel_draw_cb (GtkWidget *widget, cairo_t *cr, gpointer data)
{
GtkWidgetProfiler *profiler;
profiler = GTK_WIDGET_PROFILER (data);
gdk_threads_add_idle_full (G_PRIORITY_HIGH, toplevel_idle_after_draw_cb, profiler, NULL);
return FALSE;
}
static void
instrument_toplevel (GtkWidgetProfiler *profiler,
GtkWidget *toplevel)
{
GtkWidgetProfilerPrivate *priv;
priv = profiler->priv;
priv->toplevel_draw_id = g_signal_connect (toplevel, "draw",
G_CALLBACK (toplevel_draw_cb), profiler);
gtk_widget_add_events (toplevel, GDK_PROPERTY_CHANGE_MASK);
priv->toplevel_property_notify_event_id = g_signal_connect (toplevel, "property-notify-event",
G_CALLBACK (toplevel_property_notify_event_cb), profiler);
}
static GtkWidget *
ensure_and_get_toplevel (GtkWidget *widget)
{
GtkWidget *toplevel;
GtkWidget *window;
toplevel = gtk_widget_get_toplevel (widget);
if (gtk_widget_is_toplevel (toplevel))
return toplevel;
g_assert (toplevel == widget); /* we don't want extraneous ancestors */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_container_add (GTK_CONTAINER (window), widget);
return window;
}
static GtkWidget *
get_instrumented_toplevel (GtkWidgetProfiler *profiler,
GtkWidget *widget)
{
GtkWidget *window;
window = ensure_and_get_toplevel (widget);
instrument_toplevel (profiler, window);
return window;
}
static void
map_widget (GtkWidgetProfiler *profiler)
{
GtkWidgetProfilerPrivate *priv;
priv = profiler->priv;
g_assert (priv->state == STATE_INSTRUMENTED_NOT_MAPPED);
/* Time map.
*
* FIXME: we are really timing a show_all(); we don't really wait for all the "map_event" signals
* to happen. Should we rename GTK_WIDGET_PROFILER_REPORT_MAP report to something else?
*/
gtk_widget_show_all (priv->toplevel);
priv->state = STATE_INSTRUMENTED_MAPPED;
}
static void
profile_map_expose (GtkWidgetProfiler *profiler)
{
GtkWidgetProfilerPrivate *priv;
gdouble elapsed;
priv = profiler->priv;
g_assert (priv->state == STATE_INSTRUMENTED_NOT_MAPPED);
g_timer_reset (priv->timer);
map_widget (profiler);
elapsed = g_timer_elapsed (priv->timer, NULL);
report (profiler, GTK_WIDGET_PROFILER_REPORT_MAP, elapsed);
/* Time expose; this gets recorded in toplevel_property_notify_event_cb() */
g_timer_reset (priv->timer);
gtk_main ();
}
static void
profile_destroy (GtkWidgetProfiler *profiler)
{
GtkWidgetProfilerPrivate *priv;
gdouble elapsed;
priv = profiler->priv;
g_assert (priv->state != STATE_NOT_CREATED);
g_timer_reset (priv->timer);
reset_state (profiler);
elapsed = g_timer_elapsed (priv->timer, NULL);
report (profiler, GTK_WIDGET_PROFILER_REPORT_DESTROY, elapsed);
}
static void
create_widget (GtkWidgetProfiler *profiler)
{
GtkWidgetProfilerPrivate *priv;
priv = profiler->priv;
g_assert (priv->state == STATE_NOT_CREATED);
priv->profiled_widget = create_widget_via_emission (profiler);
priv->toplevel = get_instrumented_toplevel (profiler, priv->profiled_widget);
priv->state = STATE_INSTRUMENTED_NOT_MAPPED;
}
/* The "boot time" of a widget is the time needed to
*
* 1. Create the widget
* 2. Map it
* 3. Expose it
* 4. Destroy it.
*
* This runs a lot of interesting code: instantiation, size requisition and
* allocation, realization, mapping, exposing, destruction.
*/
static void
profile_boot (GtkWidgetProfiler *profiler)
{
GtkWidgetProfilerPrivate *priv;
gdouble elapsed;
priv = profiler->priv;
g_assert (priv->state == STATE_NOT_CREATED);
/* Time creation */
g_timer_reset (priv->timer);
create_widget (profiler);
elapsed = g_timer_elapsed (priv->timer, NULL);
report (profiler, GTK_WIDGET_PROFILER_REPORT_CREATE, elapsed);
/* Start timing map/expose */
profile_map_expose (profiler);
/* Profile destruction */
profile_destroy (profiler);
}
/* To measure expose time, we trigger a full expose on the toplevel window. We
* do the same as xrefresh(1), i.e. we map and unmap a window to make the other
* one expose.
*/
static void
profile_expose (GtkWidgetProfiler *profiler)
{
GtkWidgetProfilerPrivate *priv;
GtkAllocation allocation;
GdkWindow *window;
GdkWindowAttr attr;
int attr_mask;
priv = profiler->priv;
g_assert (priv->state == STATE_INSTRUMENTED_MAPPED);
/* Time creation */
gtk_widget_get_allocation (priv->toplevel, &allocation);
attr.x = 0;
attr.y = 0;
attr.width = allocation.width;
attr.height = allocation.width;
attr.wclass = GDK_INPUT_OUTPUT;
attr.window_type = GDK_WINDOW_TEMP;
attr_mask = GDK_WA_X | GDK_WA_Y;
window = gdk_window_new (gdk_screen_get_root_window (gtk_widget_get_screen (priv->toplevel)),
&attr, attr_mask);
gdk_window_show (window);
gdk_window_hide (window);
gdk_window_destroy (window);
/* Time expose; this gets recorded in toplevel_property_notify_event_cb() */
g_timer_reset (priv->timer);
gtk_main ();
}
void
gtk_widget_profiler_profile_boot (GtkWidgetProfiler *profiler)
{
GtkWidgetProfilerPrivate *priv;
int i, n;
g_return_if_fail (GTK_IS_WIDGET_PROFILER (profiler));
priv = profiler->priv;
g_return_if_fail (!priv->profiling);
reset_state (profiler);
priv->profiling = TRUE;
n = priv->n_iterations;
for (i = 0; i < n; i++)
profile_boot (profiler);
priv->profiling = FALSE;
}
void
gtk_widget_profiler_profile_expose (GtkWidgetProfiler *profiler)
{
GtkWidgetProfilerPrivate *priv;
int i, n;
g_return_if_fail (GTK_IS_WIDGET_PROFILER (profiler));
priv = profiler->priv;
g_return_if_fail (!priv->profiling);
reset_state (profiler);
priv->profiling = TRUE;
create_widget (profiler);
map_widget (profiler);
n = priv->n_iterations;
for (i = 0; i < n; i++)
profile_expose (profiler);
priv->profiling = FALSE;
reset_state (profiler);
}

View File

@ -1,60 +0,0 @@
#include <gtk/gtk.h>
#ifndef GTK_WIDGET_PROFILER_H
#define GTK_WIDGET_PROFILER_H
G_BEGIN_DECLS
#define GTK_TYPE_WIDGET_PROFILER (gtk_widget_profiler_get_type ())
#define GTK_WIDGET_PROFILER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_WIDGET_PROFILER, GtkWidgetProfiler))
#define GTK_WIDGET_PROFILER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_WIDGET_PROFILER, GtkWidgetProfilerClass))
#define GTK_IS_WIDGET_PROFILER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_WIDGET_PROFILER))
#define GTK_IS_WIDGET_PROFILER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_WIDGET_PROFILER))
#define GTK_WIDGET_PROFILER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_WIDGET_PROFILER, GtkWidgetProfilerClass))
typedef enum
{
GTK_WIDGET_PROFILER_REPORT_CREATE,
GTK_WIDGET_PROFILER_REPORT_MAP,
GTK_WIDGET_PROFILER_REPORT_EXPOSE,
GTK_WIDGET_PROFILER_REPORT_DESTROY
} GtkWidgetProfilerReport;
typedef struct _GtkWidgetProfiler GtkWidgetProfiler;
typedef struct _GtkWidgetProfilerClass GtkWidgetProfilerClass;
typedef struct _GtkWidgetProfilerPrivate GtkWidgetProfilerPrivate;
struct _GtkWidgetProfiler {
GObject object;
GtkWidgetProfilerPrivate *priv;
};
struct _GtkWidgetProfilerClass {
GObjectClass parent_class;
/* signals */
GtkWidget *(* create_widget) (GtkWidgetProfiler *profiler);
void (* report) (GtkWidgetProfiler *profiler,
GtkWidgetProfilerReport report,
GtkWidget *widget,
gdouble elapsed);
};
GType gtk_widget_profiler_get_type (void) G_GNUC_CONST;
GtkWidgetProfiler *gtk_widget_profiler_new (void);
void gtk_widget_profiler_set_num_iterations (GtkWidgetProfiler *profiler,
gint n_iterations);
void gtk_widget_profiler_profile_boot (GtkWidgetProfiler *profiler);
void gtk_widget_profiler_profile_expose (GtkWidgetProfiler *profiler);
G_END_DECLS
#endif

View File

@ -1,66 +0,0 @@
#include <stdio.h>
#include <gtk/gtk.h>
#include "gtkwidgetprofiler.h"
#include "widgets.h"
#define ITERS 100000
static GtkWidget *
create_widget_cb (GtkWidgetProfiler *profiler, gpointer data)
{
return appwindow_new ();
}
static void
report_cb (GtkWidgetProfiler *profiler, GtkWidgetProfilerReport report, GtkWidget *widget, gdouble elapsed, gpointer data)
{
const char *type;
switch (report) {
case GTK_WIDGET_PROFILER_REPORT_CREATE:
type = "widget creation";
break;
case GTK_WIDGET_PROFILER_REPORT_MAP:
type = "widget map";
break;
case GTK_WIDGET_PROFILER_REPORT_EXPOSE:
type = "widget expose";
break;
case GTK_WIDGET_PROFILER_REPORT_DESTROY:
type = "widget destruction";
break;
default:
g_assert_not_reached ();
type = NULL;
}
fprintf (stdout, "%s: %g sec\n", type, elapsed);
if (report == GTK_WIDGET_PROFILER_REPORT_DESTROY)
fputs ("\n", stdout);
}
int
main (int argc, char **argv)
{
GtkWidgetProfiler *profiler;
gtk_init (&argc, &argv);
profiler = gtk_widget_profiler_new ();
g_signal_connect (profiler, "create-widget",
G_CALLBACK (create_widget_cb), NULL);
g_signal_connect (profiler, "report",
G_CALLBACK (report_cb), NULL);
gtk_widget_profiler_set_num_iterations (profiler, ITERS);
/* gtk_widget_profiler_profile_boot (profiler); */
gtk_widget_profiler_profile_expose (profiler);
return 0;
}

View File

@ -1,60 +0,0 @@
#include <gtk/gtk.h>
#include "widgets.h"
GtkWidget *
text_view_new (void)
{
GtkWidget *sw;
GtkWidget *text_view;
GtkTextBuffer *buffer;
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
text_view = gtk_text_view_new ();
gtk_widget_set_size_request (text_view, 400, 300);
gtk_container_add (GTK_CONTAINER (sw), text_view);
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
gtk_text_buffer_set_text (buffer,
"In felaweshipe, and pilgrimes were they alle,\n"
"That toward Caunterbury wolden ryde.\n"
"The chambres and the stables weren wyde,\n"
"And wel we weren esed atte beste;\n"
"And shortly, whan the sonne was to reste,\n"
"\n"
"So hadde I spoken with hem everychon \n"
"That I was of hir felaweshipe anon, \n"
"And made forward erly for to ryse \n"
"To take our wey, ther as I yow devyse. \n"
" But nathelees, whil I have tyme and space, \n"
" \n"
"Er that I ferther in this tale pace, \n"
"Me thynketh it acordaunt to resoun \n"
"To telle yow al the condicioun \n"
"Of ech of hem, so as it semed me, \n"
"And whiche they weren, and of what degree, \n"
" \n"
"And eek in what array that they were inne; \n"
"And at a knyght than wol I first bigynne. \n"
" A knyght ther was, and that a worthy man, \n"
"That fro the tyme that he first bigan \n"
"To riden out, he loved chivalrie, \n"
" \n"
"Trouthe and honour, fredom and curteisie. \n"
"Ful worthy was he in his lordes werre, \n"
" \n"
"And therto hadde he riden, no man ferre, \n"
"As wel in Cristendom as in Hethenesse, \n"
"And evere honoured for his worthynesse. \n"
" \n"
" At Alisaundre he was, whan it was wonne; \n"
"Ful ofte tyme he hadde the bord bigonne \n"
"Aboven alle nacions in Pruce; \n"
"In Lettow hadde he reysed, and in Ruce, \n"
"No cristen man so ofte of his degree. \n",
-1);
return sw;
}

View File

@ -1,101 +0,0 @@
#include <gtk/gtk.h>
#include "widgets.h"
struct row_data {
char *stock_id;
char *text1;
char *text2;
};
static const struct row_data row_data[] = {
{ "document-new", "First", "Here bygynneth the Book of the tales of Caunterbury." },
{ "document-open", "Second", "Whan that Aprille, with hise shoures soote," },
{ "help-about", "Third", "The droghte of March hath perced to the roote" },
{ "list-add", "Fourth", "And bathed every veyne in swich licour," },
{ "go-top", "Fifth", "Of which vertu engendred is the flour;" },
{ "format-text-bold", "Sixth", "Whan Zephirus eek with his swete breeth" },
{ "go-first", "Seventh", "Inspired hath in every holt and heeth" },
{ "media-optical", "Eighth", "The tendre croppes, and the yonge sonne" },
{ "edit-clear", "Ninth", "Hath in the Ram his halfe cours yronne," },
{ "window-close", "Tenth", "And smale foweles maken melodye," },
{ "go-last", "Eleventh", "That slepen al the nyght with open eye-" },
{ "go-previous", "Twelfth", "So priketh hem Nature in hir corages-" },
{ "go-down", "Thirteenth", "Thanne longen folk to goon on pilgrimages" },
{ "edit-copy", "Fourteenth", "And palmeres for to seken straunge strondes" },
{ "edit-cut", "Fifteenth", "To ferne halwes, kowthe in sondry londes;" },
{ "edit-delete", "Sixteenth", "And specially, from every shires ende" },
{ "folder", "Seventeenth", "Of Engelond, to Caunturbury they wende," },
{ "go-next", "Eighteenth", "The hooly blisful martir for the seke" },
{ "go-up", "Nineteenth", "That hem hath holpen, whan that they were seeke." },
{ "system-run", "Twentieth", "Bifil that in that seson, on a day," },
{ "text-x-generic", "Twenty-first", "In Southwerk at the Tabard as I lay," },
{ "edit-find", "Twenty-second", "Redy to wenden on my pilgrymage" },
{ "edit-find-replace", "Twenty-third", "To Caunterbury, with ful devout corage," },
{ "media-floppy", "Twenty-fourth", "At nyght were come into that hostelrye" },
{ "view-fullscreen", "Twenty-fifth", "Wel nyne and twenty in a compaignye" },
{ "go-bottom", "Twenty-sixth", "Of sondry folk, by aventure yfalle" },
};
static GtkTreeModel *
tree_model_new (void)
{
GtkListStore *list;
int i;
list = gtk_list_store_new (3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
for (i = 0; i < G_N_ELEMENTS (row_data); i++)
{
GtkTreeIter iter;
gtk_list_store_append (list, &iter);
gtk_list_store_set (list,
&iter,
0, row_data[i].stock_id,
1, row_data[i].text1,
2, row_data[i].text2,
-1);
}
return GTK_TREE_MODEL (list);
}
GtkWidget *
tree_view_new (void)
{
GtkWidget *sw;
GtkWidget *tree;
GtkTreeModel *model;
GtkTreeViewColumn *column;
sw = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw), GTK_SHADOW_IN);
model = tree_model_new ();
tree = gtk_tree_view_new_with_model (model);
g_object_unref (model);
gtk_widget_set_size_request (tree, 300, 100);
column = gtk_tree_view_column_new_with_attributes ("Icon",
gtk_cell_renderer_pixbuf_new (),
"icon-name", 0,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
column = gtk_tree_view_column_new_with_attributes ("Index",
gtk_cell_renderer_text_new (),
"text", 1,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
column = gtk_tree_view_column_new_with_attributes ("Canterbury Tales",
gtk_cell_renderer_text_new (),
"text", 2,
NULL);
gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
gtk_container_add (GTK_CONTAINER (sw), tree);
return sw;
}

View File

@ -1,35 +0,0 @@
/*** BEGIN file-header ***/
#include "gtkwidgetprofiler.h"
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@filename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GType
@enum_name@_get_type (void)
{
static GType etype = 0;
if (G_UNLIKELY(etype == 0)) {
static const G@Type@Value values[] = {
/*** END value-header ***/
/*** BEGIN value-production ***/
{ @VALUENAME@, "@VALUENAME@", "@valuenick@" },
/*** END value-production ***/
/*** BEGIN value-tail ***/
{ 0, NULL, NULL }
};
etype = g_@type@_register_static (g_intern_static_string ("@EnumName@"), values);
}
return etype;
}
/*** END value-tail ***/
/*** BEGIN file-tail ***/
#define __TYPE_BUILTINS_C__
/*** END file-tail ***/

View File

@ -1,24 +0,0 @@
/*** BEGIN file-header ***/
#ifndef __TYPE_BUILTINS_H__
#define __TYPE_BUILTINS_H__
#include <glib-object.h>
G_BEGIN_DECLS
/*** END file-header ***/
/*** BEGIN file-production ***/
/* enumerations from "@filename@" */
/*** END file-production ***/
/*** BEGIN value-header ***/
GType @enum_name@_get_type (void) G_GNUC_CONST;
#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type ())
/*** END value-header ***/
/*** BEGIN file-tail ***/
G_END_DECLS
#endif /* __TYPE_BUILTINS_H__ */
/*** END file-tail ***/

View File

@ -1,7 +0,0 @@
#include <gtk/gtk.h>
GtkWidget *appwindow_new (void);
GtkWidget *text_view_new (void);
GtkWidget *tree_view_new (void);