Wiimote Perl hacks

The wiimote is a geek toy. Here's what I did with it so far.

3D Earth

I wrote this OpenGL program in Perl more than a year ago. It can display Apache access logs in real time, as geolocated spikes on the rotating planet (if your machine is powerful enough :). It was a fun way for me to learn tiny bits of OpenGL, enough to run it. I thought it would be cool to use the wiimote to control the planet, twisting and spinning the Earth with your hands. It worked pretty well, and I'm really satisfied with the result.

Fast forward…

During last couple of weeks, I managed to find some spare time to play with the wiimote again. Here's the result, the wiimote tools.

Wiimote tools

Tools it's probably not the right word. It's small hacks. It 3 different hacks in one box. I know there's already stuff out there that let you do everything like this, but honestly I don't care at all. The interesting part is writing something, preferably in Perl, to do that myself. And if my kids can have fun with it, it's the best a father-hacker can hope for… :)

Copy-paste from the README follows:

wiimote-drumkit

This is something I made for my small kids, so they could just play with sounds. You can write a small config file to assign random mp3s/wav/… to each button of the wii.

Take a look at drumkit.conf or animals.conf as examples.

Then every time you press a button, or wave the wii in the air (pretending you're playing drums), you will hear the corresponding sounds. It requires 'paplay', the Pulse audio command line player. My daughter almost managed to fork bomb my PC pressing buttons everywhere :)

wiimote-joystick

This is a quick hack that I put together to use the wiimote together with any of my favorite games as a digital joystick.

I can use it to play with mame (see pic), of course with legal roms or c64 emulators (with games I of course owned when I was a kid) and so on. Currently it works well with a few games, because of the way the keys are sent to X11, and it works really bad with other games, because of the way the keys are sent to X11. :)

Requires the X11::GUITest module, install with sudo cpan X11::GUITest.

wiimote-conductor

This is the stupidest of the lot. It can control the speed of a movie (or song?) by pretending to use the wiimote like a drunk orchestra conductor would.

It's a bit sucky because it doesn't get the actual tempo from the sound, so you have to pretend the normal (1.0x) speed is represented by wii-beats distanced by 1 second. So if you want to double the speed of the movie/song, you have to wave the wii in the air every 0.5 seconds. Pretty lame, eh? :)

Requires Audio:: Play:: MPlayer with a trivial patch I made to add the speed command.

Everything is nicely packaged here, if you want to experiment with it.

… and this is for mst, have fun!

Puppet, Fabric and a Perl alternative?

Some time later this month I'm going to write more extensively about a project that I've been working on, not continuously, but for the last couple of months. It is about small and medium scale projects configuration management and deployment.

For configuration management I evaluated several products like bcfg2, puppet, cfengine and lcfg, and I finally chose puppet.

For "the last mile", as I call it, the alternatives that I considered were fabric, capistrano, ControlTier and TheNewShinyWheel(tm)

So I settled on puppet + fabric. Puppet is a Ruby system, while Fabric is Python code. None of them is particularly fast, actually Puppet is slow, and Fabric is acceptable. The main problem I'm confronting with, after having learnt how to use these tools, is that Fabric does not support parallel processing of tasks.

This is a severe limitation for us. This was a pilot project. If it works well, it could be applied to many other deployment tasks. That could also mean that a single deployment has to send code or files to tens of servers, and you don't want to do that sequentially waiting for each task to complete.

At the moment, this is impossible to do with Fabric. There is an experimental fork in the works that might support parallel execution, by adding a @parallel task decorator, but it still requires work and a good dose of testing.

During my survey I looked for mature Perl-based deployment tools, but I failed at finding them. While Fabric is nice, I might be tempted to reconsider my choice. Any suggestions?

Undefined symbol: modperl_xs_sv2request_rec at /usr/lib/perl/5.10/DynaLoader.pm line 193

Today I was trying to run some Test::Class-based unit tests for a project I'm working on. This project has lots of functional tests that go through Test::WWW::Mechanize, so they run inside Apache and mod_perl.

What I was trying to do was testing the same code outside the Apache server, just as regular command-line-runnable tests. Being a Perl project, you have all the nice infrastructure already done for you, and so you can just run make test or Build test depending on the exact tool you're using.

However, when I run this, I got a strange error:

PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*/*.t
t/unit-tests/basic-sanity.t .. ok
t/unit-tests/handler-xml.t ... Can't load '/usr/lib/perl5/auto/APR/Request/Apache2/Apache2.so' for module APR::Request::Apache2: /usr/lib/perl5/auto/APR/Request/Apache2/Apache2.so: undefined symbol: modperl_xs_sv2request_rec at /usr/lib/perl/5.10/DynaLoader.pm line 193.
 at /usr/lib/perl5/Apache2/Request.pm line 3
Compilation failed in require at /usr/lib/perl5/Apache2/Request.pm line 3.
BEGIN failed--compilation aborted at /usr/lib/perl5/Apache2/Request.pm line 3.

The weird error is:

Can't load '/usr/lib/perl5/auto/APR/Request/Apache2/Apache2.so' for module APR::Request::Apache2: /usr/lib/perl5/auto/APR/Request/Apache2/Apache2.so: undefined symbol: modperl_xs_sv2request_rec at /usr/lib/perl/5.10/DynaLoader.pm line 193.

and specifically, undefined symbol: modperl_xs_sv2request_rec.
Why is this happening?

A search for this error message gives back very few results, and not very useful. However, this more specific search turns up fewer results, but that led me to the solution.

The first hit, in particular, I have no idea what that page says, because it's Japanese, but the code blocks are clearly referring to the PERL_DL_NONLAZY environment variable:

PERL_DL_NONLAZY

    Set to one to have perl resolve all undefined symbols when it
    loads a dynamic library.  The default behaviour is to resolve symbols
    when they are used.

    Setting this variable is useful during testing of extensions as it
    ensures that you get an error on misspelled function names even if
    the test suite doesn't call it.

AFAIK, it all boils down to the modperl_xs_sv2request_rec function not being available if your code is not running inside Apache with mod_perl loaded. So, it makes sense to run the tests with PERL_DL_NONLAZY=0 (that is, be lazy!), like the Japanese guy suggests.

However, changing that in the Makefile incantations seems to be a Royal Pain, so I just gave prove a shot. And once more, I had the proof that prove is just the way to run your test suite, because prove seems to be smart enough to set PERL_DL_NONLAZY automatically to zero.

So now, I'm running prove through a shell script, like this:

...
BASE_DIR=<project_root>
...
export CONFIG_FILE=/etc/blah-blah
export WHATEVER_ELSE=...
...
prove -I $BASE_DIR/lib $* $BASE_DIR/t/unit-tests

And that's it, all tests successful! o/

Communities in Action 2010 in Oslo

Last Monday, 10th of May, the regular Oslo.pm (Oslo Perl Mongers) meeting was a little special. In fact, there wasn't any Oslo.pm meeting, but we went to a free, one evening mini conference sponsored by several norwegian companies: "Communities in Action".

The basic idea was to put together several different communities in the Oslo area, so the conference program was diverse and exciting. There were 7 different tracks. Among them, the most interesting for me, apart from Oslo.pm, were:

  • XP (extreme programming, agile, etc…)
  • scalabin (about the scala language)
  • OWASP
  • Oslo C++ users group

Other tracks were by the NNUG, Norwegian .NET users group and IASA, some norwegian association about something…

There were a couple of colleagues from Opera, and other guys I know from Oslo.pm, but being there alone, I couldn't follow more than one track, so I tried jumping a bit between different rooms. I found the XP talk a bit boring, so I settled on the Oslo.pm track. There was a talk on rakudo * by Karl Rune Nilsen and a talk about meta-object programming in Perl vs Ruby by Matt Trout.

Both talks rocked. I think I had attended a very similar rakudo talk before, but the Ruby one was entirely new. It was funny when Matt, just before starting, tried to attract Ruby folks screaming and shouting
throughout the hotel hall :-)

After the conference, a small group of us gathered and headed over to tilt, a nice pub/pinball place, where I ended up making the day record even if I suck at pinballs…

A couple of bugs fixed on the varnish accept-language VCL extension

Today I received a report of a bug in how the Opera.com startup page was presented to some browsers. In particular, people with Brazilian language.

This was traced down to being a bug in the accept-language.vcl extension that we are using on both My Opera and Opera.com.

In particular, the bug had to do with static buffers being reused and overwritten during the Accept-Language string parsing, essentially due to my non-optimal C skills :) Now this bug is fixed and new test cases were added, so to hopefully avoid regressions in the future.

So now clients with Accept-Language containing strings like pt-BR, es-ca, zh-CN, etc… will be correctly recognized by the VCL code, and they will get the correct page served by varnish.

As always, thanks to Opera, the code is freely available, and I have to say it's not really experimental dangerous stuff anymore. It's been quite proven in the last few months (these few bugs excluded). At least your Varnish server shouldn't explode :-) Have fun!

embed.ly supports My Opera urls

On My Opera, we started using the OEmbed specification a long time ago. The goal was to provide an easy way to get metadata information, for example from albums or pictures. Example: given a picture URL on My Opera:

http://my.opera.com/365/albums/showpic.dml?album=2721921&picture=42077711

we wanted to give our users a way to extract metadata information about that URL in an easy way. That's what OEmbed is about. So you have the following OEmbed API url:

http://api.my.opera.com/service/oembed?url=http%3A//my.opera.com/365/albums/showpic.dml%3Falbum%3D2721921%26picture%3D42077711

and the result of an HTTP GET to that URL is:

{
   "width" : "3443",
   "author_name" : "giulia-maria",
   "author_url" : "http://my.opera.com/giulia-maria/",
   "provider_url" : "http://my.opera.com/",
   "version" : "1.0",
   "provider_name" : "My Opera Community",
   "height" : "2293",
   "url" : "http://files.myopera.com/giulia-maria/albums/2721921/DSC_5396.JPG",
   "title" : "April 27, 2010. Pink jasmine or pink lilac?",
   "type" : "photo"
}

So that gives you some useful metadata if you need to embed the picture in a page of yours, or even within a widget. Various sites have been supporting OEmbed for many years now. You can see a brief list on oembed.com. However, now there's a new service called embed.ly that works as a oembed "hub", as it transparently supports URLs from many different websites.

And that includes My Opera too! Try it here:

http://api.embed.ly/embed?url=http%3A//my.opera.com/365/albums/showpic.dml?album=2721921%26picture=42077711

or try it with your favourite site.

Pimp my Debian

Have you ever reinstalled your workstation and found out that your Perl scripts need a shit load of modules that you don't have anymore? Or maybe on a server?

I have. In such cases you have to:

  • run your script,
  • find out which module is missing,
  • figure out if there's a debian package for it,
  • install the debian package,
  • GOTO 10

Today I was so annoyed and lazy, that I decided to put an end to this madness. So I wrote pimp-my-debian. It's an innocent script that you can run as follows:

$ pimp-my-debian --command 'perl ./myscript'

It will keep running your command (perl ./myscript), reading its output, and if it contains something like Can't locate module Foo/Bar.pm in @INC, or Base class package "Foo::Bar" is empty, it will try to figure out a suitable debian package, install it, and retry your command.

It worked so well that I so want to use it again… :-)
Get pimp-my-debian here and have fun!

Another quick update to Ubiquity for Opera

I just pushed a small update to my Ubiquity for Opera user javascript. Two tiny changes:

  • Now the ESC key hides the Ubiquity window
  • Fixed the text selection and focus when you reopen the Ubiquity window and you had input a command before.

Thanks to Martin Å rank for contributing the ubiq_focus() fix.

To download the latest version, go to http://github.com/cosimo/ubiquity-opera/. There's also a minified version there.

MySQL alter table in a transaction

I had a quite painful experience yesterday, I would say…

We were about to run live database migrations, when I decided to try it first in a staging database server, to have a more precise idea of how long they would take. So I connected to the MySQL test system:

mysql> use myopera
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> BEGIN WORK;
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE blah ADD COLUMN xxx ...
...

The ALTER operation completed in a minute or so. Then I wanted to revert it, so I typed:

mysql> ROLLBACK;

So the transaction was rolled back. Just to double check, I verified that the table was indeed left in its original state, and to my surprise, it wasn't. Yes, the table is a InnoDB table, and yes, I had put the ALTER statement in a transaction.

Even after a ROLLBACK the table is left altered… Isn't that surprising? For me, it was. Of course, it is a documented MySQL behavior, and it's filed as bug/feature request.

Handling a file-server workload with varnish – part 2

I wrote about tuning varnish for a file server. I'd like to continue, detailing what we had to change compared to the varnish defaults to achieve a good and stable performance.

These were the main topics I had mentioned:

  • threads related parameters
  • hash bucket size
  • Session related parameters
  • Grace config and health checking

Threads-related parameters

One thing is certain. You'd better bump up the minimum threads number. When varnish starts up, it creates "n" threads. If more threads are needed, it can create as much as "m" threads but no more.

"n" is given by thread_pool_min * thread_pools. The defaults are 2 thread pools, and thread_pool_min is 200, so varnish will create 400 threads when starting up. We found that we need at least 6,000 threads, sometimes peaking at 8,000. In this case, it's better to start up directly with 7-8,000 threads. We set:

  • thread_pools = 8 since we have a 8 cores machine
  • thread_pool_min = 800

With these settings, on start Varnish will create 6,400 threads and keep them running all the time.

We also set a related param, thread_pool_add_delay to 2 ms, instead of the default I believe 20 ms. This allows Varnish to create a lot of threads more quickly when it starts up, or when more threads are needed. Using the default 20 ms value could slow down the threads creation process, and prevent Varnish to serve requests quickly enough.

Hash bucket size

Don't know much about the hashing internals, but I know we have tens of millions of files, even more, so we have to make sure the hash tables used to store cached objects are big enough, to prevent too many hashing collisions.

This is controlled by the -h option to varnishd. The default bucket size is 50023. We set it to 500009 (-h classic,500009). In this way, even if we could keep 10 million files in memory, we would only have 20 entries in each bucket on average. That's not ideal, but it's better than the default.

We didn't experiment with the new hashing algorithms like critbit.

Session-related parameters

Not so much on this particular server, but in general, we had to bump up the sess_workspace parameter. The default is 16kbytes (16384). sess_workspace controls the amount of memory dedicated by varnish to each connection (session in varnish speak), that is used as a working memory for the HTTP header manipulations. We set it to 32k here. On other servers, where we use a more elaborate VCL config, we use 128k as the default value.

Grace and health checking

Varnish can check that your defined backends are "healthy". That means that they respond to queries in the defined time, and they don't miss heartbeats. You enable health checks just by defining a .probe block in your backend definition (search the Varnish wiki for details).

Having health checks is very convenient. You can instruct varnish to extend the grace period when/if your backend is dead. This means: if Varnish detects that your backends are dead or overloaded and they miss some heartbeats, it will keep serving stale objects from its cache, even if they expired (their TTL is already over). You enable this behaviour by saying:

sub vcl_recv {
   set req.backend = mybackend;

   # Default grace period is 10s
   set req.grace = 10s;

   # OMG. Backend dead. Keep serving stuff until we recover them.
   if (! req.backend.healthy) {
      set req.grace = 4h;
   }
    
   ...
}

sub vcl_fetch {

   # Renew cached objects every minute ...
   set obj.ttl = 60s;

   # ... but keep all objects way past their expire date
   # in case we need them because backends died
   set obj.grace = 4h;

   ...

}

That's it. We're continuing to refine our configs and best practices for Varnish servers. If you have feedback, leave a comment or drop me an email.