PSiCHE:
Perl Scalable ithreaded Component Helper Extensions

Dean Arnold
Presicient Corp.
Last updated Jan. 22, 2006

Psyche Entering Cupid's Garden,
John William Waterhouse,
1904
Mythology of Psyche
 

Introduction

Venus received her with angry countenance. "Most undutiful and faithless of servants," said she, "do you at last remember that you really have a mistress? ... You are so ill-favoured and disagreeable that the only way you can merit your lover must be by dint of industry and diligence. I will make trial of your housewifery." Then she ordered Psyche to be led to the storehouse of her temple, where was laid up a great quantity of wheat, barley, millet, vetches, beans, and lentils prepared for food for her pigeons, and said, "Take and separate all these grains, putting all of the same kind in a parcel by themselves, and see that you get it done before evening." Then Venus departed and left her to her task.

But Psyche ... sat stupid and silent, without moving a finger to the inextricable heap.

While she sat despairing, Cupid stirred up the little ant, a native of the fields, to take compassion on her. The leader of the ant-hill, followed by whole hosts of his six-legged subjects, approached the heap, and with the utmost diligence taking grain by grain, they separated the pile, sorting each kind to its parcel; and when it was all done, they vanished out of sight in a moment.

Bulfinch's Mythology

Where's We're At Today

"ithreads ? Way too heavy...takes forever to create a thread, shared memory is sooo expensive. Forget about it, just fork() instead...or use POE!"

Thats the likely response you'll get if you mention threads in a Perl forum. Pretty disheartening, actually. And for Perl newbies, it will likely send them into the comforting arms of Python, Ruby, or Groovy...or back to Java, C# or, heaven forbid, C++. An unfortunate situation.

Especially when, in actual practice, using current hardware and network capabilities, it isn't entirely true.

What's PSiCHE ?

PSiCHE attempts to build on the foundations provided by ithreads and modern hardware to provide a simpler, gentler way to implement scalable applications in Perl. Some might be tempted to call it "enterprise Perl", but I dislike the "E" word, so I'll just call is PSiCHE.

PSiCHE uses Perl's natural reflection/introspection capabilities, and the ithreads capabilities, coupled with some notions borrowed from Java, to provide a simple solution to scalable application construction in Perl.

In brief, PSiCHE provides a framework for object oriented Perl applications to exploit scalability via the ithreads discipline.

For those familiar with the various frameworks built to simplify J2EE in the Java realm, much of PSiCHE may seem familiar. The intent is to "simplify, simplify".

Who Should Use It ?

If you're developing object oriented applications in Perl that need to scale, and you've got reasonably modern hardware (and maybe network bandwidth), PSiCHE may be for you. In most cases, you can write your Perl classes as before, maybe inheriting from a few PSiCHE framework classes, and implementing a few special methods that need to be specialized for, e.g., I/O hander objects, and you're ready to run. PSiCHE does its best to provide wrappers for Plain Old Perl Objects (aka, POPOs), so in many instances, you'll be able to just plug your existing classes into PSiCHE, and they'll just work.

Note that some things that might make you nervous have already been taken care of, e.g., DBI (via DBIx::Threaded), GUI development (via Tk::Threaded), or web enabled apps (via HTTP::Daemon::Threaded). Hopefully, that will simplify things a bit more.

...and Who Shouldn't ?

If any of the following applies...

...you can stop reading now, and go back to scratching your head about how to scale.

What's Next...

This document attempts to structure the PSiCHE concepts in a classic learning discipline: Foundations, Frameworks, Discipline, Adapting Existing Methods, Tips and Tools, Troubleshooting, and Futures and Solutions. I recommend you don't skip ahead, as each topic tends to be crucial to understanding its succeding topic.

Foundation: Thread Communication

The Need

The Current Solution: Thread::Queue

PSiCHE's Alternative: Thread::Queue::Duplex

Publish and Subscribe with Thread::Queue::Multiplex

A Contentious Issue: Replacing threads::shared with Thread::Sociable

Within Perl's current ithreads implementation, variables are private to each thread, and each newly created thread gets a private copy of each existing variable. All of which may seem reasonable...until your threads need to share information. Enter threads::shared, which defines a simple interface to declare a variable as "shared".

Unfortunately, threads::shared imposes a significant burden: since all threads::shared variables are managed within a single shared Perl interpretter context, a single global lock on that context must be acquired before any thread can do anything to any thread::shared variable. No matter if each thread is referencing completely different variables, and is only doing read operations, they all must first exclusively acquire the global lock before accessing the shared variables (Frankly, it calls into question the point of providing application-level locking primitives). The problem is exacerbated by the frequent reference count adjustments applied to the shared variables as various threads create and destroy proxy versions and references.

PSiCHE's answer is Thread::Sociable, which permits sharing of variables between threads (and pseudoforks on Win32) without the global shared interpretter context. While Thread::Sociable's interface is largely based on threads::shared, a modified backend is provided that minimizes the performance penalty of the highly pessimistic global shared interpretter locking on which threads:shared is heavily reliant.

Additionally, Thread::Sociable provides a native, more tightly coupled queueing solution (via Thread::Sociable::Queue) than the previously mentioned queues. Thread::Sociable::Queue merges and mimics the interfaces of Thread::Queue::Duplex and Thread::Queue::Multiplex.

Framework: Apartment Threading

Classic Threading Applications

PSiCHE's Alternative: Apartment Threading with Thread::Apartment

But There's More: Zone Threading

Discipline: Design and Documentation Tools

Use Case Scenarios

Identifying Actor and Resource Objects With Use Case Scenarios
Actor Objects in PSiCHE
Resource Objects in PSiCHE
Sharing Resources Among Actors: Thread::Resource::RWLock

Who's Doing What to Whom, and When: Sequence Diagrams

Using UML::Sequence
PSiCHE has adopted the UML::Sequence module, with some modifications, to provide an easy to use, yet fully featured, modelling tool to document the interactions of objects within a PSiCHE application.

(For a more complete description, see Generating UML and Sequence Diagrams at Perl.com)

As an example consider the following sequence description:

AtHome.Wash Car
	/* the bucket is in the garage */
    Garage.retrieve bucket
    Kitchen.prepare bucket
        Kitchen.pour soap in bucket
        Kitchen.fill bucket
    Garage.get sponge
    Garage.checkDoor
	    -> clickDoorOpener
    	[ ifDoorClosed ] Garage.open door
    * Driveway.apply soapy water
    ! Driveway.rinse
    Driveway.empty bucket
    Garage.close door
    Garage.replace sponge
    Garage.replace bucket
UML::Sequence converts this into the following image (in either SVG or raster image form):

In addition, the tool will create an HTML areamap to provide hyperlinks to the classdocs (see the next section), and to embedded annotations.

Embedded Class Documentation with psichedoc

Perl has relied on Plain Old Documentation aka POD for a long time. Much (most?) of Perl is documented in POD. Some claim to have written entire books using POD.

So the following statements will likely to be considered heretical (though I've received significant encouragement from some users). POD doesn't work for complex Perl classes.

A contributing factor to the success of Java has been its embedded documentation discipline, javadoc. Yet, whenever someone suggests implementing a similar solution for Perl, the "old hands" trot out the same tired rejoinders:

In reality, javadoc, with some minor adjustments, works just fine for Perl, thank you. And it can provide an aesthetically pleasing, and very helpful, documentation discipline. Sure, javadoc'ing a closure may be a challenge, but PSiCHE tends to eschew the use of closures. However, lack of formal type declarations doesn't mean that some explanation of method arguments and returned values is either impossible or undesirable.

I'll assume the reader agrees that some form of detailed documentation of public interfaces is desirable. To date, Perl developers have used POD as the primary (only?) tool to provide that embedded documentation. The result is an inconsistent stew of formatting and content styles that impose an additional roadblock to code reuse, due to the inconsistent documentation styles. Indeed, even finding two POD formatting tools that produce consistent output can be a challenge.

The problem is that POD is a formatting discipline, while javadoc is a content discipline. javadoc's tags are directly related to the context in which it is used, and provide a fairly natural solution to embedding documentation regarding the use of a given method of a class. POD, on the other hand, is very free form, and context free, which makes it very flexible; I have no problem believing that someone could write a book using POD. However, POD is also pretty limiting (my personal pet peeve: why doesn't POD properly handle a link tag with a URL in it ?). javadoc is a context oriented content discipline that leverages the predominant markup language of our time, HTML. POD is a context-free format oriented discipline that accomodates - barely - the HTML markup language.

To address the shortcomings of POD with respect to detailed embedded class documentation, PSiCHE presents psichedoc. psichedoc is a simple script that leverages the javadoc syntax, with some minor additions and omissions to accomodate Perl's differences, to produce nicely formatted class documentation Here's some example psichedoc output.

Legacy: Using Legacy Perl Components with PSiCHE

The Need

The Solution

DBIx::Threaded: A Zone Threaded DBI

Tk::Threaded: A Zone Threaded Perl/Tk

HTTP::Daemon::Threaded: An Apartment Threaded Web Server

Toolbox: Building and Debugging PSiCHE Applications

Assembling PSiCHE Applications

Debugging PSiCHE Applications: Devel::Psichedb

Psichedb is an attachable, browser-based, collaborative multithread/multiprocess friendly Perl debugger, based on the foundation provided by Devel::RingBuffer and IPC::Mmap.

Monitoring PSiCHE Applications: Devel::STrace

Also based on Devel::RingBuffer and IPC::Mmap, Devel::STrace is a solution for monitoring execution of running multithreaded/multiprocess applications. Like Psichedb, Strace is an attachable debugger, but without the full debugger interface. Rather, it attempts to minimize the overhead of the Perl debugger interface, and only provides a monitor capability.

Futures: What's Missing, What's Next, and PSiCHE for Perl6

Some Missing Pieces

What We Can Do About It

PSiCHE in Perl6

References