1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
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 2005/07/28.
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);
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.
|