It's official folks. The party is over.
CPUs aren't going to be getting any faster. Both Intel and AMD have switched from speed to multi-core and power-reduction and are going to be there for a while.
So how long? Well at the very least until every CPU is a dual core, and I'd probably suggest until _most_ servers are 4 CPUs. And they all chew less power than now. So a good couple of years. Sure we'll see a trickling increase, but it would seem we've run out of straight line speed.
Personally, I'm not quite mentally adjusted yet. Doing anything seriously parallel has always been a world of pain. Or at the least, it's been inelegant. Threads are are still practically a write off, forking is weird on Win32 and doing quick IPC in any meaningfully cross-platform way looks problematic. Bits work here and there, but erk...
But anything that can't do meaningfully useful and easy-to-use parallel processing is going to start to look ugly during 2007 when everything is dual core.
Of course, the great hope is Perl 6. Audrey Tang assures me we have a threading design that doesn't suck, and since Haskell has what I'm told is a decent one I have some hope there. And the explicit parallelism metaoperator would seem to be a very elegant syntax for doing that sort of thing, if used right.
But what to do about Perl 5... if there some way we can make it easier to do processing a bit more flexibly in a cross-platform and pure Perl way, and without being drawn into any one operating systems idea of how to do it.
Mostly for my own use in PITA (which I promise to launch properly soon, really!) but also in the hope that others might find it useful, I've created a new top-level namespace called Process:: and at the root Process.pm.
Process.pm is about creating classes that represent abstract computational processes that just may happen to (but don't need to be) run in an operating system process.
The easiest way to describe an object of a Process.pm subclass would be a single task that needs an interpreter thread and will consume computational resources for a time, and then end.
And you use it as follows.
my $object = MyPiCalculator->new( positions => 1_000_000 );
$object->prepare or die "prepare failed";
$object->run or die "run failed";
That's it for the API. Your Process object is created with params, it binds to any resources it needs in prepare, and then it completes the processing and cleans up during run. For simple, you are welcome to make your run method call prepare internally.
Much like the IO:: family of modules, Process:: uses subclasses and role-like sideways classes to indicate specific things.
If your process is conceptually never-ending, like a daemon, you create a subclass of Process::Infinite. This doesn't change anything codewise, but it does indicate to anything running it that it shouldn't expect it to end on it's own (this is of course only indicative and an expectation of "stoppingness", the Halting Problem applies regardless)
This might all seem a bit anally retentive, but things get a little bit more interesting when we hit Process::Storable.
By adding an extra @ISA for Process::Storable you are indicating that any object of this class can be safely frozen after new using Storable, then be thawed back to an object later and have prepare and run called on it safely with no ill effects. And secondly that if run completes successfully, it can be frozen and thawed safely in its post-run state as well.
This creates all sorts of interesting scenarios.
When you subclass this you get a free method called background, that lets you do stuff like this.
MyCacheCleaner->new( dir => '/var/cache/mine', limit => '10MB' )->background;
And now we've fired off a Process object running in its own Operating System process in the background, correctly detached from the current process for you.
I'm still feeling this concept out a bit myself but there's some interesting ideas in this area... how about Process::Distributable for tossing around to any computer with your class installed to run. Or Process::YAML so your class can be frozen to YAML, transported to somewhere else, and run in any language that has an implementation. Cross-language distributedness... golly!
I don't know where it's going to end up, but it's my first tentative step towards the sideways revolution.