kivikakk.ee

To be fair with my previous post by giving the whole story now: I called IBM. Less than 3 minutes were up, and I had everything I needed to know about my service call. That time includes time spent listening to their menu tree.

So, incredible phone support; terrible email support. Interesting how they can go so right and so wrong.

I realised something today: Ruby is my work language. I remember years ago when a group of people were discussing, I think on RubyInside (or maybe just ruby-talk), how to get Ruby into the workplace. There was Ruby Insurgency by Andy Hunt—when I review it now, it’s more or less exactly how I introduced Ruby at my workplace. It started off being used by me to do quick little hacks here and there, prototypes and the like; then I introduced it in more mission-critical places one-by-one until it formed a keystone of many of the pieces of architecture.

We have a sizable amount of code that works in production (our testing framework) entirely written in Ruby—its size is of equal magnitude with the software it’s testing. Preprocessors running over all our production code are written in Ruby. The glue that holds our pieces of architecture together are written in Ruby. We’re at the last stage, “Ruby Rules”, of the Ruby Insurgency.

And I can’t enjoy it anymore. Sad, but true. I love OCaml—I don’t think I can actually code in any other language, any more, and have the same feeling of joy that I get with ML, because it’s a very specific one, and Ruby and other dynamic languages can’t deliver it. I don’t think Ruby will be replaced anytime soon as my desktop calculator and ultra-fast script for batch processing and other text analysis, but this basically reduces it to a glorified Perl. Which, I suppose, it is.

I’ve been known to espouse the various joys and delights of Ruby’s object model, but the reality of the matter is that I rarely use it in the use-cases for Ruby that I have left—when I do, it tends to be only because the script is explicitly for one-time use or insular use, and thus will feel no restriction in appending a dozen instances to String or Class or so on. The supposedly great things that I tout the language for are the ones I use least in larger-scale projects.

Of course, this is somewhat a lie—I do use them in larger-scale projects, such as swiftest—but it’s exactly my point that it’s a work thing. While I’ll admit that I don’t have the ML nous to write anything of the complexity or size of swiftest in ML, I’m working my way very readily there in my own spare time (latest achievement: fairly complete (though minimal) lisp interpreter!), and it was only because I had the requisite knowledge on Ruby that I was able to contribute swiftest in Ruby.

That may sound obvious, but the revelation behind it is this: Ruby didn’t let me build swiftest—I did. Anyone could build a similar system in their language of choice, and while naturally the instrumentation of the resulting system and how it would look and feel would sure differ, their end result would be the same, and I daresay a lot of the architecture in any one system would map more-or-less directly onto the architecture in another. I feel the need to draw a parallel with convergent evolution here, though I think one would be neither necessary nor correct, but perhaps you can feel what I’m trying to say: even with a different set of primitives and ideals or motivations at the language level, once you start building greater levels of complexity, you tend to end up with similar abstractions, even if they’re composed in different ways.

You might wonder what draws me to OCaml. It can’t escape all the points made above, right? Well, probably not. But it jives with me even more than Ruby did when I first encountered it—and that’s not to say that Ruby jives with me any ‘less’, per se, but rather I’ve realised that I can jive with a programming language a lot more than I’ve been assuming for a long time. Jive.

I’d like to elaborate on this some more, soon

Below is the email to my company and its sister company which summarised my recent findings with IBM. My email to IBM, 9:35am:

Hi there,

I recently submitted a request with ESC+, problem number 616P496RCS.

When I spoke to the IBM representative on the phone, I requested a change of address – he did this by closing the old ticket (now in status “CCC”) and opening a new one, with number P496CBC.

Unfortunately, the new ticket (P496CBC) is not shown in the “View my requests: Australia/New Zealand” view in ESC+, so I can’t track what’s happening with my laptop.

As it has been over a week, I’d like to know what’s happening. Thanks!

Cheers,
Arlen

At 9:43am, IBM’s reply graced my inbox.

Dear  Arlen
Thank you for contacting AskIBM.

For technical enquiries, warranty claims, Recovery CDs, repairs and local IBM Repairers in Australia please contact our service centre on 131 426 (61 7 5585 3144).

For technical and service enquiries in New Zealand, please contact 0800 733 222  (64 4 576 5555).

Should you have any further enquiries please do not hestitate to contact AskIBM.

Regards

Jane
AskIBM Administrator
IBM Australia

I replied at 9:50am:

Hi Jane,

Thanks for your reply! I do have further enquiries, as it happens.

Are you able to help me at all via email? I don’t particularly want to spend all day on the phone, which is why I went to the trouble of finding an email address where I could actually contact you guys.

Your response gives the impression you didn’t actually read what I wrote at all. (Case in point: I didn’t ask for phone numbers.)

Thanks again,

Arlen

At 10:32am, IBM struck back:

Dear  Arlen

Thank you for contacting AskIBM.

For  technical support and service please contact:

131 426   (61 7 5585 3144)  if calling form Australia or

0800 733 222  (64 4 576 5555)  if calling from New Zealand.

Regards

Jane
AskIBM Administrator
IBM Australia

With my dear friend Alex’s help (i.e. he composed the entire thing), we vetoed her attempts to palm us off at 10:42am:

Dear Jane,

Thanks for getting back to me, and for again ignoring the main thrust of my email.

I apologise for the tone of this email, however your latest response has left me feeling undervalued as a customer.

I cannot see where the issue would be in having a level of basic manners and responding with “I’m sorry, but we deal with our technical queries via phone, please contact etc etc” rather than ignoring my question and responding only with the contact details.

You will note that my response to you, whilst acknowledging your actions in the conversation, also contains my own questions. Note how from my point of view this could be considered an open dialogue, whereas your responses provide me with no added benefit beyond that which an auto-responder would provide.

Moreover, your responses contain typos which make it clear that I am being responded to by a human. This adds insult to injury, as it means not only are my responses reaching a person, but that person is taking deliberate steps to ignore my questions.

So please – if I must contact your phone support (which I dearly hope is better than your email support) just answer me clearly. Do *not* give me the phone number again – it is apparent that I already have it, as it’s the only thing of any value you have thus far given me. Tell me not only that I must contact phone support, but that my continued emailing will have no effect but to further frustrate me.

Regards,

Arlen

At 11:07am, IBM raised their white flag in a pitiful act of cowardice:

Dear Arlen

Thank you for contacting AskIBM.

I am unable to provide an email address.

Please phone our service centre.

Regards

Jane
AskIBM Administrator
IBM Australia

This is why we rock.


Arlen Cuss
Software Engineer
Noble Samurai

DHL turned up just now (before 2pm) for a pick-up. I’m hereby assuming it was for me.

It was quick, but man, what an attitude.

Me: Are you from Lenovo?
DHL: I’m from DHL.
Me: O…kay… who does it say the pick up’s for?
DHL: Byte. (or something that sounds like that)
Me: Byte?
DHL: Byte.
Me: Alright..

I hand over the laptop, without battery and AC adapter as requested on the phone earlier today.

DHL: You’re lucky I’ve got a box, otherwise that’d be bouncing around in there!
Me: …… (they said on the phone he’d have a box??)

That’s it. Fast but unfortunate courier.

I learned a funny thing about the human mind this morning.

Last night I was trying to lodge a service request with IBM for my ThinkPad Edge—very, very poor quality, if I do say so myself. From a few days ago, the screen started blanking (with the laptop going into suspend) at random, though it seemed to happen most often while Misty and I were watching a DVD. It’d happen when I was using the keyboard, when I wasn’t, DVD or no DVD, eventually becoming more and more common.

This started to really frustrate me, coupled with the fact that Linux 2.6.32 seems to have a 1 in 3 chance of failing to resume from suspend on it. “Preferences -> Power Management” lets you stop it from suspending (it only locks the screen), but that was still really annoying. It turns out gnome-power-management has keys in gconf where you can actually disable any behaviour at all—I discovered that yesterday. That was ideal, but the word “ideal” is laughable when it meant that, by this stage, the LCD backlight would turn off after a few seconds of use (and with it the external monitor also turns off—the computer seemingly under the belief that I’m closing the lid?), and it would take a lot of moving the laptop’s lid back and forth before I’d just strike an angle that would leave it on for a few seconds more.

I had a go at taking it apart, but I couldn’t find the mechanism that signals whether or not the lid is closed (nothing obviously magnetic, either). I hadn’t seen any of this behaviour while using Windows on the machine, so I tried rebooting into Windows, but the symptoms were steadily getting worse.

I decided it high time to get IBM onto the scene (as they provide support for Lenovo’s machines, the two being mostly one and the same, now). I discovered that applying a strong pressure to the part of the laptop just to the right of the keyboard (near the return key and so on) actually caused the LCD to work. I had to keep it there though. This was frustrating.

So, there I am, frustratingly trying to navigate Lenovo’s support website (to lead me to IBM’s “Electronic Service Call+” website), trying to login, all with my right hand applying a firm pressure to this area right next to the keyboard. No fun.

I imagine that, when I signed up to Lenovo’s website back when I purchased the laptop, that ID may extend to IBM’s website, so I try logging in with that email address. No deal! I can’t find any password configuration that works. I choose “Forgot my password”. And here’s where the whole point of this entry comes in.

My secret question comes up, and it looks nothing like a secret question I’d ever set:

(3 * 2) * (3 * 1.5 * 2) =

That’s it. I look at it and think—surely this isn’t mine. The email address sure is, though. It annoys me that they have no recourse of “send password reset link to email”. Working from the left, I get 3×2=6, 6×3=18, 18×1.5=27, 27×2=54. I enter “54″. No dice. “fiftyfour”. Nope. “fifty four”. Nuh-uh. “fifty-four”. Nothing works.

Annoyed, I give up and register for a new account with my work address (this is all with my hand on the right side of my laptop). It takes an agonisingly long time to do that, and then even longer to lodge an “electronic service call”, the form for which seems designed more for companies with thousands of IBM assets than anything else. They even asked me for a “priority”. Sure, I’ll pick “highest”.

This morning, I wake up after some really, really strange dreams, and as I slowly manage to come to reality, Misty and I start chatting. Half-way through a sentence, I realise my brain has been working out the equation as it was written; by this stage I couldn’t remember the right hand side, but I remember that it was 6x=54 and—of course, 6 × 9! Though I’ve not heard the radio play in years, nor read the books, The Hitchhiker’s Guide to the Galaxy came to me at once, and I knew the answer must be 42.

I sprang out of bed and found the log-in form, filled out all the information, and voilà—success.

The human mind sure is strange.

På Debian

sairyx

It took me all night and all morning, but I’ve finally got Debian working on my laptop. I wish in a way that it didn’t have to be this difficult, but it turned out to be the case.

I burnt a netinst disc of 5.06 amd64, inserted it and expected it to work. Instead, I was informed that my CD drive couldn’t be detected (!) (this is while already proceeding through the installation process). A bit disheartened, I looked at the other options; TFTP, getting a full CD image (but that wouldn’t help), and realised I could try using GRUB to bootstrap the process from the local disk.

Bootstrapped the netinst with GRUB, only to be told that the harddisk couldn’t be located! Ay carumba. Looking into it more carefully, I eventually decided to modprobe ide-* (core, generic, cd_rom, etc.)—and my harddisk appeared (this also caused my CD drive to be findable again, too). So I went through, and got to the process of partitioning the disk, where I decided to format the new root partition with ext3—not an unreasonable request, I thought. The netinst (bootstrapped from harddisk) is supposed to work even when the disk it was bootstrapped from is changed. Instead, it simply hung on mkfs.ext3. I gave it a reasonable amount of time to run (30 minutes?), but no luck—the process wouldn’t even respond to SIGKILL, so I figured something had gone badly wrong.

Now that my disk to bootstrap from was clobbered, I had no choice but to rely on the netinst CD. Again, inserting the IDE modules made the CD and harddrive appear again, and I got up to partitioning the disk. I figured it might’ve been booting from the disk itself that killed the ext3 format, so I tried again. Same result! Tried again with reiserfs. And it worked (after a harrowing 3 or 4 minutes).

Having formatted / with reiserfs, it then attempted to format hda5 as a swap partition. It then errored out, telling me that hda5 was in use (“Resource in use” appeared in dmesg), and I got the “Ignore”/”Cancel” options from partman. You can try to ignore, but then it tells you that partioning failed, and you can’t proceed without that step succeeding. In the end, my only option was to tell it to have no swap partition at all (and to manually add the swap partition once the system was all working).

After that, installation proceeded more-or-less straightforwardly. Of course, wireless didn’t work in the installer, so I had to be physically connected, and the entire process slowed to a crawl about two-thirds through configuring packages (maybe because there was no swap!).

Once installation finished, I rebooted my machine. And I got about three lines of output from GRUB as it loaded the kernel, and then nothing. Woo.

Booted it in single-user mode. I get the full kernel output on the console, which stops after it loaded the SD card reader drivers. Paging up, I found it was waiting for the root device to come up. Presumably it didn’t know about the harddrive here, either, and I had no console to go modprobing in.

A few months back, I set the SATA mode to “Compatibility” (instead of AHCI) to allow a Windows XP installation (as it couldn’t find my harddrive in AHCI mode). I set it back to AHCI. And everything worked.

Well, not everything. Wireless didn’t work, graphics didn’t work properly, sound didn’t work.. I upgraded to testing, did a full dist-upgrade, then installed the latest kernel, and installed a binary driver from RealTek for the 8191SE.. and everything’s.. finally.. working.

I note that Ubuntu literally works “out of the box”, as does the installation, so this was more effort than I’m used to. Maybe I’m getting old. ;-) But anyway, hopefully going forward I’ll be able to help out with Debian in more ways, particularly with OCaml.

Actually, this post’s title is a misnomer. Pattern matching doesn’t cost, as such. Allocating costs.

In a series of blog posts, Richard WM Jones talks about OCaml internals, relating to how it manages memory. He says:

The OCaml compiler (ocamlopt) on the other hand compiles your code very literally. For example if you write:

let f (a,b) = (a,b)

then you are asking the compiler to pattern match (a,b) and construct (ie. allocate) another tuple (a, b), and that’s exactly what the compiler will do.

These sorts of “hidden” allocations are a common problem when people are trying to wring the last drop of performance from their OCaml inner loops. Even 5 instructions in an inner loop can be costly, particularly when it’s unnecessary as in the function above.

You are better off writing this function like so:

let f (x : ('a*'b)) = x

I decided to test this assertion. Two test cases:

(** atest.ml **)

let f (a,b) = (a,b);;

for i = 1 to 1000000000 do
    ignore (f (10,20))
done;;
(** btest.ml **)

let f (x : ('a * 'b)) = x;;

for i = 1 to 1000000000 do
    ignore (f (10,20))
done;;

I tested each type twice in a row (to account for potential cache issues):

celtic@azayaka:~$ time ocaml atest.ml; time ocaml atest.ml; time ocaml btest.ml; time ocaml btest.ml

real    0m31.846s
user    0m31.830s
sys     0m0.000s

real    0m31.840s
user    0m31.830s
sys     0m0.000s

real    0m23.753s
user    0m23.740s
sys     0m0.000s

real    0m23.750s
user    0m23.730s
sys     0m0.010s
celtic@azayaka:~$

And sure enough, btest.ml wins. It’s important to note that the difference was just over 8 nanoseconds per call for this example, so it’s probably not important unless it’s used in many places or in a tight loop, and is allocating things far more weighty than an int * int tuple.

Of course, if the type actually didn’t matter in the end (such as in our example), go ahead and make it more general, and let the compiler use a polymorphic type instead!

(** ctest.ml **)

let f x = x;;

for i = 1 to 1000000000 do
    ignore (f (10,20))
done;;
real    0m23.791s
user    0m23.730s
sys     0m0.030s

real    0m23.769s
user    0m23.750s
sys     0m0.000s

There’s a more interesting question from here: what about if we still match a tuple pattern, but don’t actually allocate a new tuple for our return value? There are two possible ways to do this:

(** dtest.ml **)

let f ((a,b) as x) = x;;

for i = 1 to 1000000000 do
    ignore (f (10,20))
done;;
(** etest.ml **)

let f (a,b) = a;;

for i = 1 to 1000000000 do
    ignore (f (10,20))
done;;

The results here are interesting. dtest.ml is of the same performance class as the previous fastest solutions:

real    0m23.811s
user    0m23.740s
sys     0m0.020s

real    0m23.754s
user    0m23.740s
sys     0m0.000s

I assume this means the compiler is asserting the type at compile-time (i.e. f‘s argument must be able to match (a,b), but as we do nothing with the matched definition, there is no cost).

Meanwhile, etest.ml takes more than a second longer (!).

real    0m25.099s
user    0m25.090s
sys     0m0.000s

real    0m25.099s
user    0m25.060s
sys     0m0.030s

I’m guessing this is because it’s actually having to allocate a new int to return, as it can’t return part of the (immutable) tuple. Or something.

Any comments? I’m no OCaml professor, nor indeed an academic in the field, so any comments on my tests and/or their reliability or impact would be most welcome.

Turning Down the LAMP: Software Specialisation for the Cloud talks about how their team wrote a kernel (“Mirage”) to sit right inside Xen (as an OS) to execute OCaml in the entire 64-bit address space.

It’s a great article, so check it out. This is where I’m most interested in seeing new operating systems development and research going—desktop OSes have too much history, too many interfaces that need to be supported, all in the name of backwards-compatibility and pleasing consumers. But there’s much to be said for server OSes and research!