Saturday, 2 March 2013

The only bad thing about Mason

At the moment, I'm writing a presentation about Mason2. The goal is to somehow convince my colleagues to consider using Mason. Instead of Template Toolkit.
As part of it, I thought I'd do a bit of performance benchmarking against Template Toolkit. So I put together a reasonably complex mini set of templates using both systems. Well, as complex as TT can take in reality. Which is not very much.

But anyway, let's jump straight to the bad news.

        Rate Mason    TT
Mason  901/s    --  -51%
TT    1852/s  106%    --


As you can see, with similar settings (code caching enabled) and over 10000 runs of two pages, Mason2 is twice as slow as Template Toolkit. Mason2 is still below the millisecond per page in my benchmark, but still that's quite a big difference.

As the common wisdom goes, CPU time is cheaper than programmer time, so it shouldn't be a big deal, given the huge gains of productivity you should get by using Mason2's very cool and powerful features.

Stay tuned for the full presentation to come!

PS: To follow up on the comments, feel free to have a look at the benchmark source https://bitbucket.org/jeteve/mason-pres/

J. 

Thursday, 21 February 2013

Give your application a shell (and never write any ad-hoc scripts again)

As developers, we sometimes have to help operations going smoothly by fiddling with the data "by hand" because there's no GUI to allow people doing some rare and obscure things. One common way of doing it is by connecting to the DB and writing some SQL. But often, accessing your database is not enough, because you need your application code to be run.

And for that, you need a shell.


I mean a Perl application shell

Perl offers a great module to implement this: Devel::REPL . By the way, if your using a debian based distribution and if you're wondering about the quickest way to install a CPAN module, CPAN ↔ Debian is the site you want !

Let's say your application is called 'My::Bob'. In this example, it's fully implemented in the shell script itself, because well, it doesn't do much.

So here it is, the magic bob.pl shell for your My::Bob application:


use strict;
use warnings;
package My::Bob;
use Moose;
## Application bob just holds a name and a couple of methods.
has 'name' => ( is => 'rw', isa => 'Str' , default => 'Bob' );
sub hello{
 my ($self) = @_;
 return 'Hello, my name is '.$self->name();
}
sub count_to{
 my ($self, $limit) = @_;
 if( ( $limit // 0 ) < 1 ){ confess "limit should be >= 1"; }
 return map{ $_ } 1..$limit;
}

package main;
## The shell code starts here
use Devel::REPL;

## You probably want to skip output buffering
$| = 1;
# Build an instance of your application.
our $BOB = My::Bob->new();

print "Hello, this is bob\n";


my $repl = Devel::REPL->new;

## Inject the instance of bob in the shell lexical environment.
$repl->load_plugin('LexEnv');
$repl->lexical_environment->do(q|my $bob = $main::BOB ;|);

## Tell something useful in the prompt
$repl->load_plugin('FancyPrompt');
$repl->fancy_prompt(sub {
 my $self = shift;
 sprintf ('Bob (%s) > ',
 $BOB->name()
 );
});

## Various autocompletion.
$repl->load_plugin('CompletionDriver::LexEnv');
$repl->load_plugin('CompletionDriver::Methods');
$repl->load_plugin('CompletionDriver::INC');

## Allow multiline statements.
$repl->load_plugin('MultiLine::PPI');

# And run!
$repl->run();

print "\nThanks for using Bob. Bye\n";


Now, let's look at a session:


$ perl bob.pl 
Hello, this is bob
                                                                                                                                                        
Bob (Bob) > $bob->hello(); ## Call any method.
Hello, my name is Bob                                                                                                                                   Bob (Bob) > $bob->name('Bobbage'); ## Change of name is reflected in the prompt
Bobbage                                                                                                                                                 Bob (Bobbage) > $bob->count_to(3) ## Arrays are printed
1 2 3

Bob (Bobbage) > my $count_hello = sub{ my ($n) = @_;  ## Define multiline subs                                                                                                                                                       re.pl(main):005:1* map{ $bob->hello() } $bob->count_to($n);                                                                                                                            re.pl(main):006:1* }

CODE(0x2fcbea0)
Bob (Bobbage) > &$count_hello(3) ## And call them
Hello, my name is Bobbage Hello, my name is Bobbage Hello, my name is Bobbage

Bob (Bobbage) >  ## CTRL-D ends the session
Thanks for using Bob. 

Hope this short example was useful to you. If you can build your application as an object, writing your own shell should be straight forward. Also you might want to add some credential checking before you let anyone playing with the guts of your application.

Until next time, happy coding!

Jerome.



Thursday, 17 January 2013

What Javascript programmers should learn from Perl mistakes

Although I spend most time developing stuff in Perl, sometime I have to fix Javascript code that's been written by JavaScript specialists. Sorry, ECMA script as it should be called. And the more I look at 2013 JavaScript programming, the more I can see some similarity with the state of Perl programming 12 years ago.
Remember the Perl obfuscated code contest? Basically it was all the "serious" Perl programmer boasting about being able to write the most f...d up original version of Yet Another Perl Hacker. While this was quite fun and made quite a good showcase of Perl's flexibility and expressiveness, some Perl programmers of the time were not quite serious enough and started to (unwillingly ?) use obfuscation techniques in production code, gaining Perl a reputation of being unreadable and unmaintainable, thus not fit for serious industrial development. You know the rest of the story: PHP, the offspring of 1994 Perl took over.
As programmers, we know that you can write unreadable and unmaintainable code in any language, and you can certainly write elegant things in any language too. Although I'm not sure about brainf.ck. The problem lies in the fact that non-programmers easily confuse the Programming language itself and the nasty habits of programmers. Have enough people write bad *any language* code, even for fun, and *any language* will gain a bad reputation. It comes from the extraordinary appetite our lazy human brains have for generalisation. Show enough retarded programs on TV and very soon people will think that the TV media itself is retarded.
So please, Javascript programmers, stop writing stuff like that:

var layout_options = {}, optgroups = {
                    globals: 'Public',
                    userones: 'Private'
                };
Or like that:
var block = conf[i], options, sel_conf, k, j;
Or like that:
opt.lytId == cfg.actLyt_id && opt.lytType === cfg.actLytType && (option_conf.selected = true);
Maybe some prehistoric browsers will actually run that faster than if you were using the 'var' keyword sensibly or if you were using good old 'if' statements. Otherwise, I think it's safe to assume these are completely useless optimizations, paid at the high price of unreadability. Plus, you know, text editors have auto-completion, so it's useless too to save keystrokes on variable names, specially if your code goes though some optimizer/packager in production.
Maybe I shouldn't rant about Javascript programming, maybe stuff like CoffeeScript or Dart will take over and it JavaScript will only live as an assembly language. Personally I have the feeling it would be a good thing. A higher level - cleaner language compiled to JavaScript taking all browsers specificities into account. Why not? I don't see anything wrong with that.
But JS programmers, if you love JavaScript and want to make sure it's still used in its current form over the next few years, stop writing code that's only barely readable by your fellow gurus.

Edit: Actually, someone has pointed out to me that Perl is still more popular than PHP in terms of Job offers.



Although PHP easily wins on Google fight.

Friday, 23 November 2012

Friday Time Waster: Watch the world go by in ASCII with Reuters' API

I've recently released WebService::ReutersConnect. It's a Perl modules that interfaces with the ReutersConnect's API in OO style. To demonstrate it and hopefully entertain you on this Friday, here's how to use it to watch the world go by in glorious ASCII and from the comfort of your command line. To put it shorter: The perfect Friday Time Waster.

The ingredients

To cook this recipe, you will need:



While you can install all of this with the CPAN command, I suggest you install most of their dependencies through your OS packaging system first.
If you're debian based, here are the debs to install: libmoose-perl libdatetime-perl libdatetime-format-iso8601-perl libtest-fatal-perl libxml-libxml-perl libwww-perl liblog-log4perl-perl liburi-perl liblibaa1-dev

Then just install WebService::ReutersConnect and  Text::AAlib via your favourite channel.

The Recipe

The Recipe is pretty straight forward, it goes like this:

Preamble. We just load the required packages and also make sure that Log4perl is not going to complain about lack of initialisation:

#! /usr/bin/perl -w                                                                                                                                                                             
use strict;
use warnings;
use WebService::ReutersConnect qw/:demo/;
use Log::Log4perl qw/:easy/;
use Text::AAlib;
use Imager;
Log::Log4perl->easy_init($WARN);

Building the $reuters object and querying the freshest image. Here we use the demo credentials and search for the latest picture:

my $reuters = WebService::ReutersConnect
 ->new({ username => REUTERS_DEMOUSER,
         password => REUTERS_DEMOPASSWORD
      });
my ( $item )  = $reuters
            ->fetch_search({ limit => 1,
                             media_types => [ 'P' ],
                             sort => 'date' });

Building the ASCII of the picture. We just download the preview URL and render it in ASCII using Text::AAlib:

## Load preview image                                                                                                                                                                              
my $res = $reuters->user_agent->get($item->preview_url());
unless( $res->is_success() ){
  die $res->status_line();
}

## Build and scale image                                                                                                                                                                           
my $bin_image = $res->content();
my $img = Imager->new( data => $bin_image , type => 'jpeg' ) || die Imager->errstr();
$img = $img->convert( preset => 'grey' );
$img = $img->scaleX(scalefactor => 2); ## Tweak to your taste
$img = $img->scale(scalefactor => 0.5); ## Tweak to your taste


## Build ASCII Version                                                                                                                                                                             
my ($width, $height) = ($img->getwidth, $img->getheight);
my $aa = Text::AAlib->new( width  => $width, height => $height );

Rendering the whole thing on the console. The rendering parameters are OK for me, but you might have to play with them depending on your taste/colour scheme:

## Print ASCII Image                                                                                                                                                                               
print $aa->render( dither => 0 ,
                   gamma => 1.83,
                   bright => 50,
                   contrast => 60,
                   color => 0
                 );

## And some info                                                                                                                                                                                   
print "\n    ".$item->date_created().' : '.$item->headline()." \n";
print "\n    ".$item->preview_url()."\n";

And that's it! Now you can put all of that together, or if you're lazy, you can just copy/paste the whole thing from this pastebin

Feel free to experiment with the options and the code and tell us about your improvement in the comments!

Happy coding!

Jerome.