A moment to give thanks

I'm offline for the next two weeks, visiting Morocco. The time away is quite welcomed. I don't celebrate religious holidays, but the end of the year does present a time to reflect on a year passed by. I wanted to celebrate a short list of people that have had a positive influence on me this year, and that means something to me. This list is, by far, not comprehensive.

  • Emmanuele Bassi for his hard work and dedication to bringing us a solid platform. Clutter, gtk+, glib, json-glib. Your attitude and ability to stay calm when surrounded by trolls does not go unnoticed.
  • Hub Figuière for never relenting to others revisionist history.
  • Andy Isaacson for being 5 steps ahead of everyone else. Every conversation I have with you ends up in amazing stories, a history lesson, and what we can do to make it better. It is always inspiring.
  • Jacob Berkman for the indistinguishable mix of charm and bad attitude. It was unforgettable working with you.
  • Hylke Bons for taking the rudeness and undeserved aggression too often found in our community and continuing to produce quality.

Thank You!

There are so many others, but I wanted to keep this list short.

Translucent Scrollbars

While working on mock-ups and prototypes for Builder, I realized that I can't stand those clunky bars, and they need to go. 1/3rd will like the idea, 1/3 will say they prefer scrollbars, and a third will say I'm copying mac. Comments typically just put me into episodes of depression, so I'm not enabling them. I think that's why I blog less, but that is a rant for another lifetime.

http://www.youtube.com/watch?v=bNV8-evh-VY

moving along …

Today was my last day at VMware. I'm off to do another start-up.

I want GtkBuilder+JavaScript

While having coffee with some friends a few weeks ago, I kept coming back to the thought that I need to be able to do small amounts of scripting within GtkBuilder. Especially if I'm going to switch to that from hard coding UIs in C. I figured it would take some hacking to GtkBuilder to do what I wanted. Well, it turns out not. I came to the revelation late last night, in bed, and hacked it up this morning.

First, we create GScriptJs which is a thin wrapper around Gjs. Mostly, just to be able to create an object from within the GtkBuilder file. Then, we create a custom connect func that will look for a given function in the script and attach it to the requested signal. All in all, very few lines of code. I'm pleasantly surprised.

Example GtkBuilder+JavaScript

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <interface>
  3. <object class="GScriptJs" id="script">
  4. <property name="script">
  5. const Gtk = imports.gi.Gtk;
  6.  
  7. function onClicked() {
  8. let w = new Gtk.Window();
  9. w.set_default_size(320, 240);
  10. w.present();
  11. }
  12.  
  13. function onQuit() {
  14. Gtk.main_quit();
  15. }
  16. </property>
  17. </object>
  18. <object class="GtkWindow" id="window">
  19. <signal name="delete-event" handler="onQuit" swapped="no"/>

Example GtkBuilderConnectFunc

  1. static void
  2. connect_func (GtkBuilder *builder,
  3. GObject *object,
  4. const gchar *signal_name,
  5. const gchar *handler_name,
  6. GObject *connect_object,
  7. GConnectFlags flags,
  8. gpointer user_data)
  9. {
  10. const gchar *script_name = user_data;
  11. GScriptJs *script;
  12. GClosure *closure;
  13.  
  14. g_return_if_fail(script_name != NULL);
  15. g_return_if_fail(connect_object == NULL); /* TODO */
  16.  
  17. script = G_SCRIPT_JS(gtk_builder_get_object(builder, script_name));
  18. if (!script) {
  19. g_critical("Cannot locate script %s", script_name);
  20. return;
  21. }
  22.  
  23. closure = g_script_js_get_function(script, handler_name);
  24. if (!closure) {
  25. g_critical("Cannot locate function %s", handler_name);
  26. return;
  27. }
  28.  
  29. g_signal_connect_closure(object, signal_name, closure,
  30. !!(flags & G_CONNECT_AFTER));
  31. }

Get the code at https://github.com/chergert/gtkbuilderscript.

Gom data mapper

Sorry it has been so long. I've been trying to keep busy, playing with lots of new ideas to see what pans out. I guess I throw a lot of code away because of it.

Anyway, a while back I played with making a sort of data mapper. I figured it is time to post it here to see if anyone finds interest in it. Otherwise I'll just let it continue to bitrot. It lets you map GObjects to SQL or whatever. I've also only implemented sqlite. But it works okay for that so far. There are probably still a bunch of bugs or corner cases missing.

But it lets you do some fun stuff, like relations. It can handle basic properties, relations and groups, enums, etc etc. It does not do migrations.

Defining a resource

  1. #include "mock-gender.h"
  2. #include "mock-occupation.h"
  3. #include "mock-person.h"
  4.  
  5. GOM_DEFINE_RESOURCE(MockPerson, mock_person,
  6. GOM_RESOURCE_TABLE("persons");
  7. GOM_RESOURCE_HAS_MANY("friends",
  8. _("Friends"),
  9. _("The persons friends."),
  10. MOCK_TYPE_PERSON,
  11. NULL);
  12. GOM_RESOURCE_BELONGS_TO("occupation",
  13. _("Occupation"),
  14. _("The persons occupation."),
  15. MOCK_TYPE_OCCUPATION,
  16. NULL);
  17. GOM_RESOURCE_PROPERTY(g_param_spec_uint64("id",
  18. _("Identifier"),
  19. _("The persons identifier."),
  20. 0,
  21. G_MAXUINT64,
  22. 0,
  23. G_PARAM_READWRITE),
  24. "key", TRUE,
  25. "serial", TRUE,
  26. NULL);
  27. GOM_RESOURCE_PROPERTY(g_param_spec_string("name",
  28. _("Name"),
  29. _("The persons name."),
  30. NULL,
  31. G_PARAM_READWRITE),
  32. NULL);
  33. GOM_RESOURCE_PROPERTY(g_param_spec_enum("gender",
  34. _("Gender"),
  35. _("The persons gender"),
  36. MOCK_TYPE_GENDER,
  37. MOCK_GENDER_UNKNOWN,
  38. G_PARAM_READWRITE),
  39. NULL););

And no, you don't have to use the macros if you have something more complex.

Saving a resource

  1.  
  2. GomResource *resource;
  3.  
  4. resource = g_object_new(MOCK_TYPE_PERSON,
  5. "adapter", sqlite_adapter,
  6. "name", "Jane Doe",
  7. "gender", MOCK_GENDER_FEMALE,
  8. NULL);
  9. gom_resource_save(resource, &error);

Get the code here.

smoother graphs coming

I did a bit more work on the real-time graphs during my current vacation. It has resulted in being a whole lot smoother. Primary fixes were:

  • Graph tracks time rather than "available buckets" for data points. It works so much better I feel stupid for not doing it in the first place.
  • Use floating point for positioning throughout pipeline until last possible step.
  • Render updates in thread and only blit to cairo xlib surface in main loop. This probably isn't technically safe at the moment as reference counting of images in libpixman aren't thread aware. However, it seems to work pretty well for a single rendering thread. Once that is fixed, we can scale up rendering to more threads (which helps a bit if you have a lot of visualizers in perfkit).
  • Not really a performance/smoothing fix, but the renderers are abstracted more from the graph. This means the visualizers and realtime graphs in perfkit share rendering code.

It also now works on gtk+ 3.0. Obligatory screencast below.

http://www.youtube.com/watch?v=Yw88edHU18E

Things I’ve been working on

(Animations) ...

http://www.youtube.com/watch?v=lp6ceGP-6vU
http://www.youtube.com/watch?v=AlvieV-sBJo
http://www.youtube.com/watch?v=_koPfiJ2zn0

Visualizing main loop delays

Ross suggested adding a feature to show when your main loop has been blocked. I borrowed some code from libsocialweb to do this. The orange blocks are periods of time when the main loop was delayed for more than 10 milliseconds. Probably useful for people trying to have high frame-rate/smooth animations.

Still hacking along on perfkit

Perfkit development has been continuing steadily. It's still just a toy of course; but I've gotten enough interest from people where this is a project I'd like to continue hacking on. I just added a gdk event source today that helps track down when your program is doing tons of updates. Once I get the data selection in place, you'll be able to dive in and explore the events. Maybe if I get some time during Thanksgiving vacation I can add that.

Times of various gdk events

The Case for PerfKit

I wanted to take a few moments to explain my silly little vision of perfkit's destiny. It already has the basis for some of this, however, that doesn't change the fact that it is still a toy and in its infancy. (I will continue to emphasize that it is a toy until it actually solves a non-trivial problem for me).

To explain my motivation, I need to provide a little background. While I was an engineer at MySpace, I spent a majority of my time in the so called "Dev Ops" team. We were responsible for creating tools to provide insight into our infrastructure. One tool we came to depend on every moment of every day was a performance collection system. We knew as much as necessary about each of our thousands of servers at every moment. Whether that was CPU, memory (especially page-fault information), or requests-per-second, it didn't matter. There was a simple interface to query and you had live graphs updating every second and the ability to deep dive.

Additionally, we had tools that would use this data to see what was happening on clusters of machines and respond intelligently. So if a server fell out of the standard deviation for a particular counter, the NOC could take appropriate action.

So that was nice. I miss it. I miss the instant feed-back of typing a command on the system and seeing how it affected real web-server performance.

So I kept this in mind when designing the perfkit infrastructure. I tried to create a balance that will allow us to gracefully move between the traditional "systems monitoring" space to the profiling space. Does it do this today? No. Because its just a toy and it is worthless. Will it do it in the future? Yes. I believe it is capable of it.

Perfkit is separated into a few components. There is an agent that is intended to be run on the target host. It is a goal that this agent can be light enough to run on my phone someday. Given tools will talk to the agent using libperfkit. It is a shared library that contains all the proper RPCs to communicate with the agent. The RPC transport is abstracted and I'll be adding new transports specialized for given situations. Currently, the control channel is over DBus and profiling data is sent over a unix socket. I intend to write a TCP transport.

I should also note that protocols are provided in plug-ins. So if you hate DBus and create another transport mechanism, it wont be loaded into the process.

I like scripting systems. So I created a command line interface that can connect to the agent and give you a readline based shell (with auto-completion) to interact with the agent. It's aptly named perfkit-shell. It looks something like this:

perfkit> manager add-channel
channel: 0
perfkit> channel=$1
perfkit> channel set-target $channel /bin/nc
perfkit> channel set-args $channel '-l 10000'

You get the idea. You can write scripts and pipe them in or load them from within the shell. Basic variables work too as you can see above. The $number variables correlate to the output parameters of the given RPC.

But let me repeat myself. Auto-completion. We can haz it.

I had a few problems with GObject introspection a while ago, but I'll finish fixing documentation eventually to support it. Once it is done, I'd like to make it simple to script data collection across your clusters for one-off metrics and analytics (with python or similar). This would be ideal for web shops that have a plug-in written to extract counters from Apache, Nginx, Cherokee, etc (no, those plug-ins do not exist today; in fact, no plug-ins really exist today).

Additionally, I want a simple GUI that can be used by a general sysadmin to connect to a host and do basic troubleshooting. Maybe even have some pretty uber-graph integration. I have the basis for this, but it needs a lot of love before I would subject a sysadmin to it. The ability to grab detailed system state for post-analysis is probably a good idea.

So, now, the profiling GUI. It's hard work. So if I don't move as fast as you want me to; I'm truly sorry. I already don't have a life and not sure I can move any faster alone. But lets look on the bright side. You are probably more clever and a better programmer than me and can help make it go faster.

Let me make this clear. I have no intention of replacing systems like lttng, systemtap, oprofile, valgrind, perf, ftrace, etc. My goal is to consume their data and provide it in a novel and genuinely useful way. Abstractions are leaky, so these tools will still have a purpose. I just, as a developer, can't stand to be using them every day anymore. Cause lets face it, those tools are a PITA.

But that said, it's time to start rolling up sleeves and coming up with clever ways to extract interesting information from your systems. The data visualization in perfkit utilizes clutter. I think that will allow for some pretty cool OpenGL based visualizers in the future.

Will you help me?