schmerg.com http://schmerg.com meercat's posterous posterous.com Fri, 30 Sep 2011 03:06:00 -0700 Couple of bugs in Chrome http://schmerg.com/couple-of-bugs-in-chrome http://schmerg.com/couple-of-bugs-in-chrome

Finally got round to reporting a couple of annoying bugs in Chrome (well, actually in WebKit I suppose as they seem to also occur in Safari) with regards to SVG use.

 Test cases: http://www.mysparebrain.com/svgbug.html

Logged as http://crbug.com/98391 and http://crbug.com/98392

Here's hoping I can get rid of my nasty hack-arounds that force redraws at appropriate times...

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Fri, 20 May 2011 01:32:00 -0700 F1 elapsed time lapcharts on f1datajunkie http://schmerg.com/f1-elapsed-time-lapcharts http://schmerg.com/f1-elapsed-time-lapcharts

Been doing some visualisations of Formula1 timing charts, based on the work of Tony Hirst.

Published a short piece on his f1datajunkie blog here with the results

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Thu, 19 May 2011 03:44:00 -0700 Tracking updates in web libraries - a small development pattern http://schmerg.com/tracking-updates-in-web-libraries-a-small-dev http://schmerg.com/tracking-updates-in-web-libraries-a-small-dev

My webapp uses various API's and in particular it pulls in things like Twitter's widget.js - which doesn't have a github home or similar (unlike, say, underscore.js that I can track from its source repository).

I could save my own copy and have my webapp always use that, but that's not such a great idea as when twitter change their API, they also change widget.js to compensate.

So my webapp always pulls in the master authoritative copy, but then I tend not to notice when it changes - and sometimes this breaks my assumptions about how it works (also, changes in widget.js are a good way to track changes to certain API details that I access outside of the widget.js library itself).

So, as there's also no RSS feed about updates or similar, I instead store widget.js in my source repository, even tho my app doesn't use the copy I've stored, and in my development workspace I regularly regularly fetch the latest widget.js (for me, this is in the script to restart my personal development environment, launch the webserver etc but you could do it in a cron job)

   wget -O js/3rd/widget.js http://twitter.com/javascripts/widgets/widget.js

And thanks to the wonders of distributed source code control systems and their "no check out required" model (I use bzr, the same is true of git and others) then if the authoritative version hasn't changed, then this has no effect, but when it does change, I suddenly see the file as modified in my "modified files" report ("bzr status"), and I can diff the new against the old and see if I need to react accordingly.

It's more of a hack than anything else, but works surprisingly well, and has stopped me being caught out (especially with "silent" changes where there's no official communications about such things).

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Thu, 12 May 2011 01:25:00 -0700 Other projects - extensions for Google Chrome http://schmerg.com/other-projects-extensions-for-google-chrome http://schmerg.com/other-projects-extensions-for-google-chrome

I wrote a couple of small extensions for Google Chrome, aimed particularly at small annoyances for developers.

It's a great web browser for developers, and there's the Web Developer extension amongst others, but these are two extensions that I can't find elsewhere

  • JsError is a minimal extension to flag errors in a page (typically in the javascript) without the need to open the developer tools (which may trigger breakpoints and the like) within Google Chrome™.
  • ForceReload is hard reloads the current tab to overcome caching issues when using Developer Tools for Google Chrome™

I should put the code up on github (it's only a few lines) but there are the links anyway.

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Thu, 12 May 2011 00:51:00 -0700 Other projects - my github account and UglifyJS http://schmerg.com/other-projects-my-github-account-and-uglifyjs http://schmerg.com/other-projects-my-github-account-and-uglifyjs

I've been adding some features to UglifyJS - a rather nice JavaScript parser / compressor / beautifier that is itself written in JavaScript.

It implements a JavaScript 1.5 parser, and then has various routines to walk the AST doing things like renaming variables and collapsing selected expressions.

I've added the ability to safely replace selected global symbols with constant values (which can then allow the minifier to collapse entire sections, like #ifdef in C++) which has been pulled into the main tree, and the ability to spot and shortcut constant expressions involving &&, ||, and ?: (ie eliminate the RHS when a true constant value on the LHS means that the RHS will never be evaluated).

I've also added the ability to mangle selected object property names, which obviously needs some care, but is great for obfuscating internals and can shorten long method names etc. This change is only in my fork for now - https://github.com/schmerg/UglifyJS (see the mangleprops branch)

I also toyed with the idea of extending the parser to understand some features of later versions of javascript (eg the very useful let statement of 1.7) and have an option to compile them down to javascript 1.5, so that

var x = 1, y =2; if (something) {   let x = x+y;   console.log("X is now "+x+" and y is "+y); } console.log("X ends with value "+x); <div></div>

would be re-written as 

var x = 1, y =2; if (something) {   (function(x) {     console.log("X is now "+x+" and y is "+y);   }(x+y); } console.log("X ends with value "+x); <div>

Yeah, I know about things like coffee-script, but I don't want to be debugging something too far away from my original source, and I hope eventually javascript 1.7 will be supported in more browsers (in which case I can stop using this conversion)

And I'm also thinking about inlining selected methods - I know javascript engines do this internally, but there are sometimes big wins to be had from inlining trivial functions (which you've coded a such to avoid repeating the same expression endlessly). Again this is a bit like the pre-processor in C++, but because it would be done as part of the proper parse process (rather than limited text substitution) then I think it could be done much more safely.

Anyway - I'll post things to github as I go...

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Wed, 09 Mar 2011 06:28:00 -0800 check_goodrcptto - a qpsmtpd plugin for checking recipients against qmail config http://schmerg.com/checkgoodrcptto-a-qpsmtpd-plugin-for-checking http://schmerg.com/checkgoodrcptto-a-qpsmtpd-plugin-for-checking

I use qpsmtpd, a sort of mod+perl for SMTP, to front end my SMTP server. This lets me configure various checks in the name of blocking spam and managing mail for my private domain. There are plugins to check messages before accepting them (scan headers, check the body with SpamAssassin, greylist senders or blacklist senders, check for certain bad behaviour typical of spambots etc) and plugins to deliver mail to various back end systems.

I use this to front end qmail which, amongst other features, has nice handling of aliases including wildcard addresses - so after geting various 'dictionary spam' attacks (mail sent to random names in the hope of hitting a valid user) as well as getting spurious bounces from the joe-jobbing activities of spammers, I wanted to have qpsmtpd understand which addresses were valid and which weren't.

As a result, I wrote the following plugin that knows how to parse the various qmail config files for user assignments and aliases.

It may not be perfect - in particular

  • it's written against an old version of qpsmtpd - I think there are conveniences in newer versions to tidy up some logic
  • it knows about qmail files and config setup, so isn't very generalised for anythign other than qmail
  • it assumes it'll be able to access the various files that qmail reads - this is true for my setup, YMMV
  • it's not in github or launchpad or similar (but may be soon)

but if you're using qmail behind qpsmtpd and you use the assigns file or similar, then you may find it handy.

<div> <pre>=head1 NAME check_goodrcptto =head1 DESCRIPTION A qpsmtpd plugin checks that the name recipient is valid according to the qmail config and refuses the mail otherwise. See http://wiki.qpsmtpd.org/ for details of qpsmptd itself =head1 CONFIG Takes the name of the qmail assign file - normally /var/qmail/users/assign =head1 AUTHOR Written by Tim Meadowcroft - http://schmerg.com Published under the same license as Perl itself - you're free to use this as you see fit. =cut sub register { my ($self, $qp, @args) = @_; die "Requires the path of the assign file (usually /var/qmail/users/assign)" unless (@args > 0 and -f $args[0]); my $assign = ReadAssignments( $args[0] ); die $assign unless ref $assign; $self->{_assign} = $assign; $self->register_hook("rcpt", "rcpt_handler"); } sub ReadAssignments { my $lines = slurp($_[0], sub { [ grep(!/^\s*#/, @_) ] } ) or return "Can't read the assign file $_[0]"; chomp @$lines; # last line should be a single dot return "Assign file not properly terminated" unless $lines->[-1] eq "."; # extract simple assignments first # =address:user:uid:gid:directory:dash:extension: # Messages for <address> will be delivered as user <user>, with the # specified uid and gid, and the file <directory>/.qmail<dash><extension> # will specify how the messages are to be delivered. # # +prefix:user:uid:gid:directory:dash:prepend: # Messages received for <prefix><rest> will be delivered as user <user>, # with the specified uid and gid, and the file # <directory>/.qmail<dash><prepend><rest> will specify how the messages # are to be delivered. my %a; foreach (@$lines) { my $type = substr($_,0,1,""); my($address,$user,$uid,$gid,$dir,$dash,$ext) = (split(":", $_), ("")x7); if ($type eq "=") { # got a user $a{user}->{$address} = { user => $user, dir => $dir, dash => $dash, ext => $ext }; } elsif ($type eq "+") { # got a prefix $a{prefix}->{$address} = { user => $user, dir => $dir, dash => $dash, ext => $ext }; } } return \%a; } sub slurp { my $file = shift; my $fh; open($fh,$file) or return undef; my @lines = <$fh>; close $fh; return @_ ? $_[0]->(@lines) : \@lines; } # $recipient is a Mail::Address object, see if it looks deliverable sub rcpt_handler { my ($self, $transaction, $recipient) = @_; $self->log(LOGDEBUG, "check_goodrcptto of ".$recipient->user); return (DECLINED) if $recipient->user eq ""; # we only check recipients for the domains we accept - let any relayed # mails pass thru (assuming that relaying is allowed) including # no hostname (so plain "postmaster" and "abuse" works) my @rcpthosts = $self->qp->config("rcpthosts") or return (DECLINED); my @localhosts = ($self->qp->config("me"), "localhost", qx(hostname), ""); chomp @localhosts; my $host = lc $recipient->host; return(DECLINED) unless grep($_ eq $host, @rcpthosts, @localhosts) > 0; # Look up this user and see if it looks like a valid user my $user = $recipient->user; $self->log(LOGDEBUG, "check_goodrcptto: $user needs checking"); if (CanBeDelivered($user => $self->{_assign})) { $self->log(LOGDEBUG, "$user accepted"); return DECLINED; } my $sender = $transaction->sender->address; $sender = "" unless defined $sender; $self->log(LOGDEBUG, "check_goodrcptto: $user is rejected, tell $sender"); # genuine mistake or, more likely, spammers flooding us return(DENY, "No such account - mail to $user not accepted here") unless (not(defined($sender)) or $sender eq ""); # bounce of email form a non-existant user - recommend SPF return(DENY, "No such account as $user - checking SPF records would prevent bouncing of joe-job emails"); } # Returns a name if we believe a message can be delivered to the specified # user, or undef if not... sub CanBeDelivered { my($user,$assign) = @_; # Look up this user and see if it looks like a valid user # Delivery will be according that user's ".qmail" or the defaultdelivery file return $user if exists $assign->{user}->{$user}; # if the user isn't directly listed, check the prefixes, longest first foreach my $prefix (reverse sort {length($a) <=> length($b)} keys %{$assign->{prefix}}) { if (substr($user,0,length($prefix)) eq $prefix) { # this prefix matches the specified user part of the email address my $v = $assign->{prefix}->{$prefix}; my $rest = substr($user,length($prefix)); my $dotqmail = $v->{dir}."/.qmail".$v->{dash}.$v->{ext}; foreach ($dotqmail.$rest, $dotqmail."default") { if (-f $_) { my $d = slurp($_, sub { chomp @_; return join(", ", grep(!/^#/,@_)) }); return $v->{user}." ($d)"; } } } } return undef; } 1;

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Mon, 07 Feb 2011 17:50:00 -0800 Force Reload - an extension for Google Chrome™ http://schmerg.com/force-reload-an-extension-for-google-chrome http://schmerg.com/force-reload-an-extension-for-google-chrome

Web developers often find that, after using Developer Tools, the browser caches their files. So if they change a source file and reload, the browser doesn't use the new version, but continues with the old version (see for example http://code.google.com/p/chromium/issues/detail?id=8742 for reports on the issue).

Personally I've found closing the tab and opening a new one helps - so this is a mininmal extension that does just that. It's my first extension, and only a few lines of code... it works for me, and I hope it works for others.

You can find the extension on the Chrome Web Store

The icon used is courtesy of newmoon's handywork at http://code.google.com/p/ultimate-gnome/

 

The new version (1.1) of the extension includes an option (disabled by default) to catch the Ctrl-F5 keystroke and override the browser's builtin behaviour, but please note that when first installed, even if this option is enabled, it will not catch the keystroke on tabs that are already open until the page is otherwise refreshed... but any new pages will behave as required.

If it doesn't work how you'd expect, then you can contact me as meercat on gmail, or add a comment below. It would help if you could briefly describe

  • whether you're using the toolbar button or the keystroke to invoke the extension
  • what version of chrome you're running (and platform)
  • what version of the extension you're using
  • how I can contact you !!

 

 

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Sun, 21 Nov 2010 15:30:00 -0800 The Trip http://schmerg.com/the-trip http://schmerg.com/the-trip

So maybe I feel some affinity with Steve Coogan because we grew up in the same part of the same small town, and at the same time (as far as I know), but while I've appreciated his work and Rob Brydon's, I've never really felt that close to the bits of their work I've liked, and have freely skipped the parts that seem excessive.

But the new show, The Trip, is a BBC triumph. Undoubtedly it helps if you know who the 2 characters are and the back stories of their public and private personas (but hell, there are American critics who it seems are only comprehensible if you're intimate with their entire works) but I'd like to think that even without that knowledge this new show of a few, short 30 minute episodes about 2 people with history and baggage, is just some of the most interesting, honest, intelligent and illuminating TV I've ever seen.

On the way it mercilessly rips the piss out of all sorts of cliches that are such holy cows that they normally can't be touched: ironic road trips, middle age conceits, the very art of food criticism, amusing chat techniques (professional and amateur), celebrity as superman, comedian as everyman, the educated version of male bravado... It's like a meta-critique of meta-criticism (which is obviously not meta-meta-criticism, or have I just laid myself open to similar ridicule?).

The fact it's all filmed in HD and mixes what appears to be genuine footage of at least some of the people involved (the sign of a good meta-level anything is not being patronising when they want to show the authentic item underneath) makes it all doubly delicious - did they enhance somehow the way Steve Coogan's head appears so small in comparision to the headrests in the Range Rover when set against the skyline of the Lake District and the muted colours of the various autumnal scenes, or is that just part of the understated way it's been filmed? I don't know, and given how the show works I feel it's one of the few genuine cases where to ask what of the incidental was intended and what just happened, what was scripted and what was ad-lib, what was set-up and what happened in hindsight, would be to ruin the show itself. The story line and the various external character interactions are obviously planned, but how many of the smirks and jibes, the monologues and repeated themes, the reactions and the sneers, are character or character actor... I don't think I'd believe the truth if you told me.

I've missed the "normal slot" so I'm watching it on digital catch-up but if you haven't seen it, grab it while you can. I swear than in 3 or so hours it'll tell you more about people and some of the ways we genuinely interact than 10 times as much of the The Sopranos, The Wire, or almost anything else I can think of.

Less is more and all that... if I've made it sound all noble and humourless and worthy, it's not, it makes me cry laughing, but when some government finally manages to dismantle the BBC and sell it off in constituent pieces to various vultures and pornographers, this is the sort of show that will be rediscovered in 20 years time and held up as an ideal of the sort of thing we've lost.

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Thu, 07 Oct 2010 01:20:00 -0700 Concurrent programming is hard (so don't do it yourself) http://schmerg.com/concurrent-programming-is-hard-so-dont-do-it http://schmerg.com/concurrent-programming-is-hard-so-dont-do-it

Writing code to be concurrent is hard and, I'm convinced, almost always the wrong model. We all know threading is hard, and leads to all sorts of subtle errors, but I'm pretty sure that no layer of dressing this up nicely will really get rid of the fundamental problems.

My particular bugbear is composability of concurrent code - how do a I write a component that executes concurrently but in a way that suits the concurrency needs of any arbitrary caller while maintaining the encapsulation of its functionality. Let's say my component has its concurrency implemented properly and in particular it can perform its work concurrently to make best use of a multicore or multi machine environment - but how does it know how much concurrency to use? I don't know if, to the caller, the execution of my component is the critical path and should use as many resources as it can to complete in the absolute shortest time possible, or whether it's not at all critical and should execute using the minimum concurrent resources as they're intended to be dedicated to some other components which are the critical path.

With explicit threading, people tend to simply make the component split its work into as many threads as it can, and then let the machine scheduler decide which threads will run, but even if thread creation and admin overhead were zero (which it isn't) the fact is that the machine scheduler doesn't arbitrarily know which threads are critical and which aren't and so the more threads (and IPC calls and communication resources etc) each component makes, the more resources they'll be effectively stealing from the true critical components.

So one suggested approach is to write components that, in addition to their inputs, also take some sort of control block that specifies what resources it can use and how it should use them ("maxthreads" and "thread priority" values), but this is a very poor composability model - what if my component then needs to use a number of others as part of its execution, without knowing precisely how those components work, execute, and consume resources, then there's no good way to take the control block I've been given and interpret how to specify control blocks to those subcomponents.

And of course, if the concurrency requirements and performance are influenced by some non-trivial characteristic of the input data, say not just the number of items in a list but depends on the values involved, and it in fact requires some partial solution of the problem to determine how much concurrency can be achieved, then the composition of an overall solution from encapsulated components becomes horribly more complex.

Another way to address this is for components to examine their environment and adjust their execution depending on what they find, but the critical path issue arises again. Just because there are execution units available and idle (assuming I can determine this) doesn't mean that, for optimal execution of the system overall, that I should go ahead and use them... it may well be that those units are being 'held' to be used by some other component that's not ready to execute yet (it's waiting for its inputs to arrive) but that will be the critical calculation when it's ready to run.

Without composition, I have no way to build components that can be used to construct large ad-hoc programs for a truly efficient concurrent execution. Anything more complex than an embarrassingly parallel model becomes a one-off special case construct, or is made in way that shoehorns my code into some concurrency framework that probably cripples my way to express a problem and delivers only a fraction of the performance that could be achieved given a particular problem and a particular set of resources.

So I devised a little model to avoid this - a functional concurrent language model where everything is composable. There's no explicit concurrency because the model itself can determine the concurrence capability of every single statement (much like a modern compiler and CPU can see chances to boost performance with out-of-order execution) and then assemble larger concurrent blocks. Every component can be written as simply a statement of the calculations required including use of other components, and the concurrency is determined dynamically in advance of execution but only when a complete composition is executed. The same components can be used at multiple points in such a solution, but the concurrency demanded of each one is independent of the others. A program written in this way will dynamically change its behaviour depending on the execution environment - it balances the load across the given resources aiming to find an execution schedule that completes in the minimum time possible, that time being the time required for the critical path as determined for those execution resources (including the cost of communicating between execution units where required). Running the same program (with the same inputs etc) on two different execution environments that differ in available resources will result in different critical paths.

It's not a perfect solution of course, as it stands it makes some simplifying assumptions, and as a small but working model it has certain limitations - in particular the model would require expanding to deal with arbitrary dimensionality of the problem expression. And while functions are composable, it imposes certain limitations on operations such as passing functions themselves as parameters or return values.

But it has some fascinating characteristics, certain whole program optimisations become available, and as it balances the loads it takes communication times into account. So it doesn't just blindly assign chunks of work to arbitrary execution units but can take account of the fact that you typically have a grid of multicore machines and making data such as inputs and outputs and other artefacts (task completion and related admin info, memoisation caches etc) available between cores is orders of magnitude quicker than communicating the same information between machines. So it can decide when, for example, it's worth doing local (per machine) or global memoisation of certain operations. And given its whole program optimisation, it knows the point at which no further resources will boost execution any further - given an excess of execution resources it will determine the a minimal subset of those resources it needs to meet the calculation demands. This is, admittedly, possibly a sub-optimal minimal set (a better or exhaustive scheduler may be able to do better), but it at least knows that it has no way to use further resources and in fact will organise itself to load the execution units in an optimal way and leave other resources completely spare rather than spread itself too thinly.

And given its strongly functional constraints it's also ideally suited to repeated calculations with perturbations to the inputs - the calculation and memoisation model can be tuned so that it performs only the minimal partial recalculations required for any changes. And those repeated partial recalculations can take account of, but are in no way constrained to, the resources that were used for the original calculations. The partial recalculations will each have their own critical path depending on the data changed.   This has, needless to say, huge benefits for certain classes of problems.

But where next ? It's an intriguing prospect, but is the sort of thing that I should probably investigate in a more academic environment. It's only a small model, a prototype to illustrate the principles and show what could be done... anyone fancy sponsoring a PhD for a truly concurrent language and execution model ?

 

No.. thought not... oh well, back to re-inventing the way we organise ourselves and maybe I'll publish the language and code sometime. 

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Tue, 21 Sep 2010 06:54:00 -0700 Cuckoo Hill traffic campaign http://schmerg.com/cuckoo-hill-traffic-campaign http://schmerg.com/cuckoo-hill-traffic-campaign

For anyone looking for the campaign to do something about the speed and general safety of traffic on Cuckoo Hill in Pinner, there's a private community blogsite http://cuckoohill.posterous.com - contact me if you'd like to join

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Thu, 16 Sep 2010 13:30:33 -0700 IE9 Beta - bug with modifying transformations on SVG elements http://schmerg.com/ie9-beta-bug-with-modifying-transformations-o http://schmerg.com/ie9-beta-bug-with-modifying-transformations-o
zsvg.xhtml Download this file

Mini self-contained HTML doc with embedded SVG to illustrate a
possible issue with IE9 Beta (logging it with the team).
Not the prettiest doc or bit of code internally, but this way it's a
single file - display updates as expected in Opera, Firefox, and
Chrome, but only updates for the first change under IE9 beta
(v9.0.7930.16406) on Win7 32-bit.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Thu, 16 Sep 2010 04:32:00 -0700 IE9 Beta - quick test and review from an SVG developer's perspective http://schmerg.com/ie9-beta-quick-test-and-review-from-an-svg-de http://schmerg.com/ie9-beta-quick-test-and-review-from-an-svg-de

I tried the "IE9 Platform Preview" last month, and blogged my biggest complaint (lack of foreignObject support), but of course that was not even a beta, and had no real UI on it.

So the IE9 beta has now been released, and it's worth giving a try.. so I did.

DISCLAIMER: This is on a VM (admittedly with plenty of CPU and 8Gb of RAM), so some things like the sluggish responses below might be caused by that - I disabled the GPU rendering options in the advanced options and it made things run.. differently...

First impressions - the UI is much cleaner than previous facelifts they've done, of course it still pushes hotmail and bing and associated sites as defaults, but at least they keep them out of the way until you go looking for them. Looks quite chrome-like without being a pure and simple copy ("inspired by" perhaps), and hopefully they've ditched all that skinning nonsense (yeah Windows Media Player - that's you I'm looking at).

The search settings and home page(s) seem rather more complex than you'd think would be needed - what with "Search Providers" and "Search Accelerators" - I dare say the distinction is important but if it's too many terms for me to be bothered even to look into, I hate to think what the average home user or enterprise user will make of it. And as for the search provider, I don't mind giving Bing a try, but just as an exercise trying to change Bing for Google took several attempts (I found the settings box doesn't seem to update when you change settings, so you have to keep on closing it and re-opening it to see if anything has happened after you choose to add something).It just doesn't feel simple and transparent, to be honest it feels almost like they're trying to discourage you from changing such things.

Notifications (about default browsers, add-ons, extensions and the like) are nice and subtle, but putting them at the bottom of screen seems maybe overly subtle - I missed a few of them down there, but will have to keep a peripheral eye open.

What about my SVG complaints ? Well first off, I won't revisit the foreignObject issue (unless someone has a nice surprise for me) but gave my heavily SVG dependent app (lots of SVG content but not necessarily complex) a try.

It rendered all the outer HTML (ExtJS GUI) parts quite well, and where it doesn't (popup menus in the wrong place, element sizing wrong), I expect that'll be because the ExtJS framework is making "corrections" for previous versions of IE. I tried turning on IE8 Document Mode (inside the developer tools) to check this, but of course then my SVG breaks completely. I hope tweaking the framework (or a new version from sencha.com) will fix much of this once everyone gets their hands on (and head around) IE9.

And the SVG ? Well mixed results - it rendered them mostly fine for a first attempt. Some of the text flowing seems to have gone all over the place (the logic works fine under Opera, Chrome, FF 3 and 4, Safari etc), but I expect it'll be something silly like checking bounding box units or the like. And some text has just rendered as a solid filled black rectangle - again I expect it'll be reasonably trivial (of course I wanted all my text to actually be embedded XHTML with markup and CSS and proper flowing of text etc but that's the 'foreignObject' topic again).

The mouse interactions seem very sluggish, so using the debugger I started firing some calls straight into my code, and got some very strange results. Where I have a couple of transforms over an area (a scale and a translate), if I change the scaling then nothing seems to happen for about 3 or 4 seconds.. then it changes, but text items that ought to be scaled don't change. Similarly the translations don't show until a few seconds delay (at least the text moves here). Other browsers do this very snappily. Might be something I'm doing wrong (but again it works on the others) or caused by the VM (see disclaimer above) but looks like I'll need to draw up various testcases and maybe implement special handling for IE if I decide to support it at all - bother.

Until I can get the scaling, transformations and mouse interactions working fine I can't say much about speed, but I will say that the delay from start of page load to rendering the first screen (involving several AJAX calls and a lot of on-the-fly DOM construction) seems pretty snappy... comparable to Chrome, quicker than FF3.x

Other points of note ?

Well there's no bookmarks bar that I can find other than putting an entire favourites panel down the left - my bookmarks bar mostly holds bookmarklets these days (bit.ly and the like) and the bar seems a bit too bit to justify keeping open all the time. Chrome has the bookmarks bar disabled by default but lets you turn it on if you want, which seems a reasonable approach - I couldn't find a similar option in IE9.

Developer tools seem slick (again Chrome sets the bar for me here) - I don't know if everyone in Microsoft has double widescreen monitors but again it seems to prefer putting, for example, the javascript console alongside the script window rather than underneath it which seems a perverse use of screen space. I'll have to use them a while to see how well they stack up - Chrome does have a problem for me with losing breakpoints between reloads, and the developer tools sometimes seem to lock themselves to old versions of a page in the cache so I have to regularly close the tab and start a new one. And the 'find element by click' (Ctrl-B under IE developer tools) seems to work properly with SVG whereas this tends to fall down under Chrome a bit (the bounding box is rarely correct). The network profiler seems comprehensive, but I miss Chrome's filter (see all resources, or just CSS / Images / XHR etc) when I've got lots of AJAX calls and small bitmaps and the like to manage. But overall the devleloper tools look impressively comprehensive.

So will I exclude IE9 ? Probably not.. I won't bend over backwards to support it before at least the first service pack or two, but I'd like to make it work before then if I can (does it sound too patronising to say something like 'if only to recognise what they've achieved in a very short time' ??). It's a good start, and my guess is that it'll force the pace of browser development forward again (actually I'd say FF3 and Chrome have done that and stung IE into responding), but the measure will be how well they react to 'real world' cases rather than potted compliance tests, automated unit tests, and performance benchmarking suites - it would help if we could post feedback and access the bugtracking system without more "you need a microsoft LiveID account etc" stuff, but I can't expect the dog to lose all its fleas overnight.

Roll on SP1 and IE10...

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Wed, 15 Sep 2010 02:59:00 -0700 Failing to get on with python ("have a nice day") http://schmerg.com/failing-to-get-on-with-python-have-a-nice-day http://schmerg.com/failing-to-get-on-with-python-have-a-nice-day

So I'm a longtime perl hacker, and never really bothered to learn
python - I couldn't see that it would give me anything too different
to justify me using it (cf knowing languages that fill different
niches - F#, C++, javascript, C# [yuck], smalltalk, prolog etc).

But then I started using Google App Engine, which provides a Java or a
Python API, and so I figure it's time to get acquainted.

And bits of it I like - the builtin library is much larger and cleaner
than perl, I can live with whitespace-instead-of-braces (altho without
the functional constructs of F# I fail to see significant benefits and
it doesn't half make some refactoring operations very error prone),
and for the most part it's not too different. Some things are just
typical "context switch" annoyances in a multi-language project and
are not a fault in python (remembering to use "&&" or "and", quoting
keys in object/dict literals, "self"/"this", "false"/"False"/"FALSE"
etc).

But the bits that annoy most are it's like they've copied perl, but
not caught what it's about, where "regularity" seem to have ground out
"humanity" - like "pydoc" vs "perldoc".

perldoc gives me something first off. It might go on to give me to
much, or have to go on about how something changes in different
contexts, or I might have to "perldoc perlfunc" to find builtin
functions by category, but generally I can find what I want and it
tries to put the most important stuff first and the more obscure stuff
later.

pydoc on the other seems perversely geared to first telling me all
sort of internal admin gubbins. Trying to remember something dumb like
how to check if a key exists in hash/dict/object I can do "pydoc
dict", but what do I get first up ?


-- Help on class dict in module __builtin__:

class dict(object)
| dict() -> new empty dictionary
| dict(mapping) -> new dictionary initialized from a mapping object's
| (key, value) pairs
| dict(iterable) -> new dictionary initialized as if via:
| d = {}
| for k, v in iterable:
| d[k] = v
| dict(**kwargs) -> new dictionary initialized with the name=value pairs
| in the keyword argument list. For example: dict(one=1, two=2)
|
| Methods defined here:
|
| __cmp__(...)
| x.__cmp__(y) <==> cmp(x,y)
|
| __contains__(...)
| D.__contains__(k) -> True if D has a key k, else False
|

First off I get constructors, sort of useful, although not as useful
as a brief word on what the class is and does.
The explanations are that great computer science invention -
explanations that leave you knowing less, so now I have to look up
what "iterable" and "mapping" objects are - are these vague concepts,
interfaces, base classes, generic terms, duck-typing style interfaces
etc.
But hey, I didn;t even what these, so what follows .... hmm, lots of
methods that start and end with "__" - a classic sign of "These are
internals, don't use them, don;t fiddle with them unless you REALLY
know what you're doing, please pretend they don't exist". So why are
they at the top of the helpfile ?
And then after these somewhere come the normal methods

| clear(...)
| D.clear() -> None. Remove all items from D.
|
| copy(...)
| D.copy() -> a shallow copy of D
|
| get(...)
| D.get(k[,d]) -> D[k] if k in D, else d. d defaults to None.
| has_key(...)
| D.has_key(k) -> True if D has a key k, else False

Explanations of the fewest possible words, well ok, these are the
basics, but written in pseudo-code in a mixture of the language and
bits that aren't in the language (is "->" part of the function
definition syntax like some functional languages - not that I've seen)
- pardon my WTF !

The documentation looks like it's been generated (spare me please from
the default output of doxygen and javadoc and the like - it's like
reading the code with all the helpful bits removed) and in that
brain-dead way of 'here's all the details in alphabetical order, we
have no idea of any structure or importance so we've sorted it, just
to be sure that if there was any logical groupings in the source then
we've destroyed that tiny little accomodation of human-to-human
communcation too'.

Consistency, regularity, homogeneity are all good, but when it comes
at the cost of practical use, human accomodation, communication,
navigation - well then it sucks.

I'd draw a comparison with the contrast between a shopping mall where
all the malls are identical in size, colour, decoration, all the shops
are the same size, and all the shop assistants have that same glazed
"have a nice day" look (but can't actually do anything like look in a
stock room or contact a supplier) and a city with nonsensical road
layouts, arbitrary names, some rubbish shops, some sullen assistants,
but in general the "big bright" shops are on the major thoroughfares
and the specialist places are in pokey back streets. You might have to
look for service, but you can get it, and you can remember the streets
by their look, their feel, their smell. And when you walk into your
favourite tech shop and the new guy behind the counter grins and says
"have a nice day", well, you turn on your heel and walk out pretty
damn smart to find somewhere different.

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Tue, 14 Sep 2010 00:39:27 -0700 Limited invitations to mysparebrain.com http://schmerg.com/limited-invitations-to-mysparebraincom http://schmerg.com/limited-invitations-to-mysparebraincom Added an invitation mechanism to www.mysparebrain.com that makes it
easier for me to show people what I've been planning for the last few
months, and getting useful feedback already from the handful of people
who've seen it.

Now to see if I can get anyone else interested enough to fund getting
some help to implement the next set of features...

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Fri, 10 Sep 2010 15:00:47 -0700 Good old rock and roll http://schmerg.com/good-old-rock-and-roll http://schmerg.com/good-old-rock-and-roll Few phrases scare me more than an aging rocker declaring he's "going back to good old rock'n'roll", what usually follows is a miserable boring plodding track so instantly forgettable that I struggle to name names (except for the obvious "anyone who had a hit before 1970") but made me think all through my younger years that "good old rock and roll" must be some incredibly steaming pile of whatever.

What they actually mean is "I done run out of ideas" and "I don't understand all this new stuff and am spending increasing amounts of time reminiscing about my younger days" and "wouldn't it be good if these things that resonate with me had the same effect for everyone".

But without the mass of people who think "yeah, that reminds me of when we thought that was new and exciting" then it simply fails.

Nice to see that the trap can be avoided, usually by those whose who didn't achieve mass-appeal in the first place, meaning I can finally enjoy a Nick Cave album for more than 7 minutes...

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Sun, 22 Aug 2010 13:42:00 -0700 SVG support in IE9, close but should try harder http://schmerg.com/svg-support-in-ie9-close-but-should-try-harde http://schmerg.com/svg-support-in-ie9-close-but-should-try-harde

So Microsoft made great promises about how Internet Explorer 9 would comply with all the standards and, in particular, add support for SVG that has been totally absent in IE before, but is increasingly well supported by other browsers.

A new era of open-ness from Microsoft with regards to web technologies ? Well not really: first off getting a preview involves all the usual microsoft twists and turns, and then it seems support for the standards falls somewhat short.

One of the key features of the standard open technologies is how they interoperate and provide extensibility, but while the IE team might be working hard to implement much of the standard (and are to be applauded for doing so), the key extensibility features of SVG (the <foreignObject> tag, that lets you then put HTML or similar within an SVG document, much as you can put SVG within an HTML document - http://www.w3.org/TR/SVG/extend.html) is not supported and, according to bug 571625 in the bug database (I'd post a link but guess what, it's not open to public view, you have to have an account AND then apply to be able to view it) it's not supported by design (for the common reader, this means that they know of the feature but have made a concious decision that they will not implement it).

quote: "The issue you are reporting is by design. Internet Explorer 9 does not support the forgetObject [sic] element."

Now that's the funny thing about standards - to implement a standard you have to implement it all... you can't pick and choose. You're allowed mistakes, oversights, accidental omissions, differing interpretations of ambiguous details etc but you can't just say "I don't like this bit and I'm not doing it". Especially when it comes to key items like extensibility that are designed to make sure that a standard can be built upon and, well... extended.

If they'd said "Oh, that feature's a bit of a biggy, we've not really done that much on it yet, and what's there is a bit buggy so it won't be turned on for this beta/preview", or provided some limited implementation, then I'd understand.

But when a bug reporting the problem is closed with "Not a bug - behaviour as per design" then that's very different.

Some might read all sorts of interpretations into this... I'll leave that to them

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/628872/police-traffic-705328558.jpg http://posterous.com/users/5BhBkLk7rfBn Tim Meadowcroft spindle cottage, cuckoo hill Tim Meadowcroft
Thu, 19 Aug 2010 13:07:00 -0700 My spare brain http://schmerg.com/my-spare-brain http://schmerg.com/my-spare-brain

Now available at http://www.mysparebrain.com/ - it's invitation only, but give me a shout if you want to try it before the rest of the world joins in...

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/628872/police-traffic-705328558.jpg http://posterous.com/users/5BhBkLk7rfBn Tim Meadowcroft spindle cottage, cuckoo hill Tim Meadowcroft
Thu, 01 Jul 2010 05:34:09 -0700 Test from a contributor http://schmerg.com/test-from-a-contributor http://schmerg.com/test-from-a-contributor Seeing how group facilities work with posterous.com

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/628872/police-traffic-705328558.jpg http://posterous.com/users/5BhBkLk7rfBn Tim Meadowcroft spindle cottage, cuckoo hill Tim Meadowcroft
Tue, 29 Jun 2010 09:22:00 -0700 Porting to python http://schmerg.com/porting-to-python http://schmerg.com/porting-to-python

Hmm, wonder if Google App Engine would be the best way to host this, initially at least.

Means porting the back end of python (which I seem to always type as 'pythin'), and changing the database, but it wouldn't be THAT much work I think....

Would make launching a beta service that much easier not having to manage authentication, failover, scaling etc etc in too much detail

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat
Fri, 04 Jun 2010 15:53:00 -0700 Clearing out the garage http://schmerg.com/clearing-out-the-garage http://schmerg.com/clearing-out-the-garage

2 days and counting... good job it's not anything serious like we're moving house, or dead.

 

Permalink | Leave a comment  »

]]>
http://files.posterous.com/user_profile_pics/566864/DSC00386.JPG http://posterous.com/users/5emkbXKB06C5 meercat meercat