Why Squeak is not the answer, part 2
Error handling (or god forbid, exception handling) is one of the weak parts in Squeak. A great deal of course comes from its dynamically typed nature. However, the greater impact probably comes from the utter lack of guard clauses in most core librares I've seen so far: Objects will happily accept any kind of parameter and continue to wrack havoc on them until the debugger, at some later point (IF we are lucky), stops the travesty.
Let's move on to BitBlits, where the lack of parameter checking and the absence of proper initialization quickly crashes your VM. Why use BitBlits at all? Because Morphics are crap. More precisely, they feature:
- poor performance (I guess all the redrawing with overlapping Morphic instances doesn't come for free),
- a hideously complex class hierarchy
- undocumented models (say, the model for PluggableListMorph)
- a hard-to-access event loop (read: no ready-made support for signals & slots),
- a complex API (only for the base class Morph itself "Morph methodDictionary size" returns 1165 methods, yikes).
Naturally, while using BitBlits or Forms most work is actually done by Squeak primitives, that is, external C code that is called by some Squeak wrappers. At this point proper argument checking becomes paramount, or else:
-
Division by zero (3.10, win32/linux)
| blit form | form := Form new. "form setExtent: 0@0 depth: 32." blit := (BitBlt destForm: form sourceForm: nil halftoneForm: nil combinationRule: Form blend destOrigin: 0@0 sourceOrigin: 0@0 extent: 0@0 clipRect: (0@0 extent: 0@0)). blit copyBits.
Note the out-commented line, which would prevent the VM crash. Appearantly the form's depth isn't initialized. The funny part starts when you replace "destForm: form" with "destForm: Object new", which triggers the proper error handling and prevents the VM crash as well.
-
The magic bitmap (3.10, linux-only)
picture := Form fromBMPFileNamed: 'bigbitmap.bmp'.
The comment at the top of this method reads "deprecated". Sadly, bitmaps are much faster than any compressed image format, even after the initial reading (oops?). More importantly though is that we have different behaviour (crash/no crash) depending on the platform where this is executed. Wait a moment - a VM? Platform-dependant? Actually, this is not the only example, many Form methods will not work with the Linux VM. But instead of telling you, they'll happily crash the VM, too.
Oh well, at least Squeak is good when it comes to runtime optimizations, like any other VM. And loop unrolling is so basic it is hardly worth to test it. Or is it?
-
Let's try a simple loop, with the inner loop manually unrolled (add:to: adds arg2 to arg1 and stores the result in a member):
MessageTally spyOn: [ (1 to: 10000) do: [:unused | self add: 1 to: 1. self add: 2 to: 2. self add: 3 to: 3. ]. ].
This executes in 4ms on my machine.
-
OK, now outer loop & inner loop:
MessageTally spyOn: [ (1 to: 10000) do: [:unused | (1 to: 3) do: [:idx | self add: idx to: idx. ]. ]. ].
WTF?! 17ms? Well, one quick optimization is to store the range (interval) of the inner loop like so: innerLoop := 1 to: 3.
-
The code then becomes:
| innerLoop | MessageTally spyOn: [ innerLoop := 1 to: 3. (1 to: 10000) do: [:unused | (innerLoop) do: [:idx | self add: idx to: idx. ]. ]. ].
+1 for everything (but variables) is an object, -1 for code obfuscation, +1 for getting execution time down to 12ms. But still. WTF?!? Does the code really spend 8 precious milliseconds in the loop variable handling (with other words, 67% of the execution time)?
(My personal) conclusion: Squeak fails at getting basic stuff right. The things it gets right (reflection/introspection, fast development round-trips) are fantastic! But it suffers from a big NIH syndrome so that instead of wrapping useful and established libraries you are left alone with an incomprehensible "self-documenting" class library. Also, wrapping C libraries using the foreign function interface seemingly requires recompilation of the VM ... platform independence, anyone?
I'd welcome comments correcting my perception problems with Squeak!