Gtk2-Perl Startup Time Poll Results

The gtk+ developers are considering adding real introspection info to gtk+ and friends, for the benefit of all language bindings. While pondering how we could make use of this in Gtk2-Perl, i wondered, "Will our startup time be adversely affected? What could we do to mitigate the effects of that? And, hey, what's our current startup time like, anyway? How can we compare, or justify optimizations, without a baseline? And why am i talking to myself like this?" Without further ado, i wrote a little script to time the load and initialization of the modules, and was surprised by the small numbers i got. So, the obvious next step was to pass the script on to others to see what kind of numbers they got.

The poll data (csv) consists of 31 data points from 21 respondents. Being a rash muppet, i'll consider this statistically viable data and draw sweeping, generalizing conclusions from it. :-)

Times, in seconds
First LoadTypical Load
GlibGtk2GlibGtk2Gtk2->init
Minimum0.0090.0320.0080.0250.008
Maximum0.7121.2270.0860.7591.092
Average0.1460.4310.0220.0840.091

The difference between "First Load" and "Typical Load" shows that many operating systems have a first-time penalty for loading a library image off of disk, but keep that library cached in ram to reduce the penalty for later loads. This makes a difference of an order of magnitude, as we see here.

What is involved in the load time? First, perl looks up the requested pm file in its library path; once it finds the file on disk, it compiles and evaluates it. The gtk2-perl modules are XS extensions, using DynaLoader, so at evaluation time, perl looks up the dynamic library associated with the extension and loads it. After loading, it "bootstraps" the extension by calling a specially-named function. For typical extensions, this function creates a symbol table entry for each xsub in the library, so that perl knows not only which subroutines are available, but what C function to call when that subroutine is invoked. In addition to this, the gtk2-perl extensions also perform a bunch of hash table insertions and @ISA manipulations to set up the associations of gtk+/gobject types to perl package names, effectively glueing together the perl and GObject type systems. (For more information on this process, see the gtk2-perl xs binding design document, the binding how-to, and the Glib::xsapi manpage.)

Newer versions of gtk+ have more object types, and that means that when the bindings are built against newer versions of gtk+, the bindings do more work at type registration time. The data from this poll doesn't illustrate that, however, as there were not enough data points from multiple versions on a single machine. In fact, the one such pair of data points (versions 2.4.x and 2.6.x on my own machine) was inconclusive; the first run was faster with 2.6.x, and the typical run was faster with 2.4.x, but the differences were miniscule.

The time to call Gtk2->init is broken out separately, because most of the time spent in that call is spent inside gtk_init, which in turn calls XOpenDisplay. This function opens a socket to the X server, which may be remote or local, depending on your setup. A local connection starts very quickly, but the time for a remote connection depends on many factors, including network congestion and the number of routers in the connection path, and can vary randomly from one run to the next.

The next time somebody on slashdot says "who actually uses the remote display capability of the X window system, anways?!?", you can respond, with proof, "One quarter of gtk2-perl users do, that's who!"

Connections by type

Not all operating systems are equal, of course. Native Win32 can't do remote display, for example. This brings to mind the question, "What operating systems do gtk2-perl users use?" This graph shows the definitive answer from our statistically perfect random sample set of 31 records from 21 users:

Operating systems

Another burning question, from the point of view of support, is "What versions of gtk2-perl are people using?" Here's breakdown of the numbers from our poll:

Gtk2 versions in use

Even numbers in the hundredths place denote a stable version, e.g. 1.04x and 1.06x. At the time of this poll, 1.061 was the current stable version, so it looks like most people are current. We even have several on the bleeding edge (1.072 is the version in HEAD), and one very naughty person using an old unstable version. Dan, it's time to upgrade your 1.054 machine. ;-)

Speaking up being up-to-date, you may have noticed that the timer script printed the compile-time and runtime versions of glib and gtk+. For those who may not know, gtk2-perl can be built against any stable version of the gtk+ C libraries, which allows us to have one actively-maintained stable version at any given time (important because CPAN only makes available the current version). However, the version against which you compile the bindings determines the features that will be available to you from perl. Therefore, it is possible to have weird installation issues. For example, 1.040 added support for the new widgets in gtk+ 2.4.0, including the new FileChooser. Suppose you had gtk+ 2.2.3 and installed Gtk2 1.040, then later upgraded gtk+ to 2.4.2; your Gtk2 will still complain that Gtk2::FileChooser is an unknown type! Why? Because it was compiled against 2.2.3, which didn't include the GtkFileChooser. The solution is to recompile the bindings. *

So, how many of our respondents' bindings are up to date? About 80%.

Are your bindings up to date?

There you have it.

-- muppet

Mon Jan 31 21:38:38 EST 2005


* Well, yes, i've thought of ways other than evil conditional compilation to support multiple versions, but #ifdef performs the best and is the most portable. The best alternative involves looking up C symbols at runtime, and binding their xsubs only if the symbols are found; however, this would incur a runtime penalty (for all the symbol lookups), would be painful to maintain (because all function invocations would have to be indirect to allow linking), and could be a big portability problem (it's not clear whether DynaLoader's portable wrappers, e.g. dl_find_symbol_anywhere, could be used for this; i suspect not).