More servicesWindows Live
HomeHotmailSpacesOneCare
 
MSN
Sign in
 
 
Spaces home  Tablet UML News on LivePhotosProfileFriendsMore Tools Explore the Spaces community

Tablet UML News on Live

May 03

Behind the Scenes at the 2008 Michigan All-State Bonsai Show

In its 10th year, the Michigan All-State Bonsai show is presented by the Frederik Meijer Gardens and Sculpture Park. It runs today (May 3) and tomorrow.

Clubs in attendance include:

Plus we have unaffiliated artists, as well as trees from the Gardens' own collection!

To learn more about Bonsai, start with The National Bonsai Foundation. You may also be interested in the following upcoming events:

  • Sensei Steve Jetzer is offering beginner classes. The next six week class starts May 6, so you'll have to hurry. For reservations, call 616.459.9496.
  • June 21: West Michigan Bonsai Club is holding a Japanese maples workshop/lecture/demo.
  • June 21: Four Seasons Bonsai Club of Michigan presents a demonstration by Bonsai Master Roy Nagatoshi, creator of the Bonsai trees from the movie Karate Kid III.
  • June 22: At Four Seasons Bonsai Club of Michigan, Master Nagatoshi leads two workshops for paid participants.
  • June 28 and 29: Wildwood Gardens presents a Bonsai BBQ with Bonsai Master Sukosolvist, owner of the Royal Bonsai Gardens in Stoughton MA. Master Sukosolvist will present demos and workshops. For reservations, call 440-286-3714.

And now, on with my show photos!

I didn't get names for all of the people (or any of the trees!), but here are some photos from the show.

7

My friend Amy Fowler (a.k.a. Pilga), my sister Anita Buckowing (a.k.a. show chair), and Sue Smalley (a.k.a. ever-helpful volunteer) work the registration table.

6

Amy, Tim Priest (assistant show chair, and chair for the 2009 show), and Anita sorting out registrations.

10

Dean Bull and Steve LeWarre set up the show tables and maintain the Gardens collection.

18

Evan and Madison Priest give a demonstration of Bonsai techniques.

19

Jeff Black demonstrates the making of Bonsai pots.

29

The official name is Gilded Champagne Gardens Chandelier by Dale Chihuly, but I always think it looks like Cthulhu's cousin.

1

Gene Deci inspects the club table for the Sakura Bonsai Society.

8

The Bonsai Society of Kalamazoo sign.

13

The Sakura club table.

15

The general club table, with information and trees from the West Michigan Bonsai Club, the Four Seasons Bonsai Club, and the Bonsai Society of Kalamazoo.

57

The poster for Master Nagatoshi's visit.

 11

A vendor preparing for the show.

12

More vendor prep.

4

Julie Francke (our helpful rep from the Gardens), Anita, and Jerry Peters (an exhibitor from the Four Seasons Bonsai Club) discuss the show.

3 14 16 17 21 22

People and trees (before the exhibit was officially open).

58

And we're open!

59

I thought this was about trees. What are all these stones doing here? (It's called suiseki, the art of selecting, polishing, and presenting stones.)

55 56

Tim Priest teaches a class on Diaza carving. (Diaza are the stands for suiseki stones.)

24 25 26 27

The Steve and Dean Show: Steve and Dean share the techniques they use for tending the Bonsai trees at the Gardens. That tripod thingy -- they call it simply "the apparatus") -- lets them suspend a tree while they clean out the roots for repotting.

5051525354

The vendors at work.

28 29 30

Oh, yeah, and then there were some trees. (My apologies to the artists for my lousy photography!)

31 32 33

And more trees.

34 35 36

And still more trees!

37 38 39 40

And I'm not even close to photographing every tree in the show.

 41 42 43

These were just the ones I could capture before the crowd got too thick for me to navigate.

 44 45 46

We have a total of 127 trees...

 47 48 49      

...from 44 artists!

5

Here's my contribution to the show.

20

Here's my office. I'm not there (who ya think's taking the picture?), but Amy is.

April 25

Concern vs. Worry vs. Obliviousness

Concern

Worry

Obliviousness

"Has this happened yet?" "Oh, no, what if this happens?" "This could never happen."
"How likely is this to happen?" "Oh, no, what if this happens?" "This could never happen."
"How can we tell if this happens?" "Oh, no, what if this happens?" "See no evil, hear no evil, speak no evil..."
"Can we prevent this from happening?" "Oh, no, what if this happens?" "This could never happen."
"What will be the impact if this happens?" "Oh, no, what if this happens?" "No problem..."
"Can we prepare for that impact?" "Oh, no, what if this happens?" "Cross that bridge when we come to it."
"Can we manage that impact if it happens?" "Oh, no, what if this happens?" "Cross that bridge when we come to it."
"Who will be responsible for watching and managing this?" "Oh, no, who will we blame if this happens?" "I didn't do it!"
"We'd better do something about this!" "Somebody'd better do something about this!" "This could never happen."
"There's nothing to do about this right now, so let's focus on what we can do." "Oh, no, what if this happens?" "Looks like smooooooth sailing ahead."

Which column describes your project management techniques?

Disclaimer: This has nothing to do with any of my current projects or clients. The person who inspired this already knows who he is, and is firmly in column 1. Any other resemblance to actual persons or events is purely coincidental.

No llamas were injured in the making of this post.

 

April 18

Moonfall: I Don't Get It...

I've decided: Jack McDevitt is my favorite modern SF author. He writes my kinda SF: hard, hard, hard, with real characters facing real situations with only science and courage and maybe a little faith on their side. There's not nearly enough hard SF for my taste out there, and most of what there is these days is military hard SF. Not that there's anything wrong with a good David Weber or John Scalzi story; but I prefer stories about exploration and colonization, light on the aliens, heavy on the realistic technology. Allen Steele does that pretty well, along with Ben Bova and Kim Stanley Robinson; but I think Jack McDevitt does it better.
 
Now I'm reading his novel Moonfall. By all rights, this should be one of my favorites, because my favorite setting is the near-future exploration of the Solar System. But somehow, I bought this book, and lost it in the stack before I could read it. So then I forgot I had it. So I bought it again, and again lost it in the stack, and again forgot I had it. And yes, during a recent book search, I found three copies. This time, I determined to read it. And I'm loving it. (And hey -- now I have one copy to read at home, one for the car, and one spare.)
 
But while I'm no expert on astronomy and orbital mechanics, and while I'm only two-thirds of the way through, I'm confused. In fact, I just don't get it.
 
The premise -- no spoilers here, because this is almost all on the cover -- is that, during a total Solar eclipse, we detect a comet. This is an extrasolar comet. Every comet we've known up to now has been part of the Solar System, so they can't travel faster then the Sun's escape velocity. If they did, they would escape (by definition). Because this comet is from outside the Solar System, it's larger than usual comets, and traveling 5 to 8 times as fast. It's a deadly missile, on a collision course with the Moon. And when it hits, the Moon will shatter; and because the USA will be facing the Moon at the time, we'll get the worst of the resulting meteor rain. So the book tells the story of the government and the people first denying the problem and then facing the consequences. (Yes, yes, some of this sounds familiar; but it's a good story even so. Judge it on its own merits.)
 
But it's the particulars of the timing that have me confused.
 
The eclipse reaches totality over Ohio at 12:30 p.m. on April 8, 2024. That means that, roughly speaking, the Sun and the Moon and the Earth were in a straight line at that time. That also means that the far side was directly facing the Sun, and the Moon was almost directly over the Eastern USA.
 
The comet hits the Moon -- somewhere on the far side, to be specific, though that leaves a lot of wiggle room -- at 10:35 p.m.on April 13.
 
Now the book says that the Eastern USA was able to view the Moon during the impact. And I just don't get it. This picture will illustrate:
 
Moonfall
 
As best I can figure, at 10:35 p.m., the Eastern USA would be roughly 160 degrees away from the line from the Sun to the Earth, having rotated almost half way around. (The Sun-Earth line will also have rotated roughly 5 degrees, which adds some imprecisions to my later numbers. This is cocktail napkin astronomy, not the real thing.) Meanwhile, the Moon would have traveled roughly 5 days along its 29.5 day orbit, or around 60-70 degrees (depending on how you figure it). Now I'm no astronomer. I don't calculate orbits. But the best I can see is that the Moon and the Eastern USA might be within 90 degrees of each other, which (I think) would put the Moon nearly over the horizon, if not over it. And if I got the travel directions wrong, they might be as much as 140 degrees apart, putting practically the whole Earth between them. I'm not sure how the Eastern USA can get a good look at the impact.
 
Furthermore, the premise is that the comet hits the far side, thus blasting a lot of debris our way. Well, if the Moon has traveled only 60-70 degrees around, then only roughly half of the far side is facing the sun; and since they discovered the comet while they were watching the eclipse (with properly approved eye protection, kids!), then only half the far side would be facing the comet. And so the bulk of the debris blasted loose from the Moon would be blasted away from the sun; and given the angles, that seems like it would be at an angle that would mostly miss the Earth as well. Sure, some of it would fall our way; but the impact angles don't line up well. I can imagine some of it launching into a long elliptical orbit that might hit us hard later (and indeed, I think that's coming in the part I haven't read yet); but debris falling directly on us is hard for me to envision.
 
But I'm an amateur astronomer at best. Maybe there's something here I'm missing. After all, Mr. McDevitt had consultants from NASA and the U.S. Naval Observatory helping him out. But I just can't see how it lines up. Feel free to tell me where I'm being stupid, if you can figure it out.
 

Somewhere Out There, Duelists Are Weeping

 
Swords on the wall.
 
Choices including Vindaloo Pork, Pork porterhouse, Whitefish Grenoble, Fish in a Bag, Tandoori Chicken, Savory pies, Butter Chicken curry, Stilton Steak, Guinness Beef, Fish and Chips, Indian Shrimp, Black Bean Chili Cod (Sautéed Cod), Railway Lamb Curry, Vegetarian Curries, Pub Burger, Bombay Dog, Indonesian Satay, Scotch Egg, Singapore Wings, Curried Chicken Wings, Bubble and Squeak, Stacked Naan, Beer Battered Shrimp, Black Bottom Pie, Peanut Butter Pie, Sticky Toffee Pudding.
 
And in case you missed it: Sticky Toffee Pudding. Oh, my word, what a treat!
 
My favorite Gaelic Storm album playing on the stereo.
 
And free WiFi.
 
So why are Duelists weeping?
 
Because they're not here.
 
And because this is the beer list they're missing out on: Kaliber, Martens, Murphy’s Red, Abbot Ale, Woodpecker Cider, Harp Lager, Tennants, Red Stripe, Wexford Irish Crème Ale, St. Pauli Girl Dark, Whitbread Pale Ale, McEwan’s India Pale Ale, Old Speckled Hen, McEwan's Scotch Ale, Hobgoblin, Amstel Light, Mackeson, Bass Ale, Merlin’s Ale, Fullers’ London Porter, Fiddler’s Elbow, Black Sheep Ale, Old Jock Ale, Monty Python’s Holy Grail Ale, St. Peter’s Old-Style Porter, John Courage, Guinness on tap, Fuller’s ESB on tap, Newcastle Brown Ale on tap, and Boddington’s Pub Ale.
 
Plus Copperidge Cabernet Sauvignon, Copperidge Chardonnay, Copperidge White Zinfandel, Red Rock Merlot, Moore’s Creek Shiraz, Indigo Hills Pinot Noir, Gabbiano Pinot Grigio, Schmitt Riesling, Kendall Jackson Chardonnay,
Fonseca Bin 27 Port, Dow’s Fine Ruby Port, Dow’s Trademark Port, Dow’s Boardroom Port, Taylor Fladgate 10 year Port, Taylor Fladgate 20 year Port, Noval 10 year Port, Noval 20 year, Curious & Ancient 20 year Port, Oban 14yr Single Malt Scotch, Cragganmore  12yr Single Malt Scotch, Dalwhinnie  15yr Single Malt Scotch, Lagavulin  16yr
Glenkinchie Single Malt Scotch, Talisker  10yr Single Malt Scotch, Aberlour Single Malt Scotch, Laphroig Single Malt Scotch, McClelland’s Single Malt Scotch, and Macallan Single Malt Scotch.
 
And because those are all wasted on me, of course, but would be greatly enjoyed by them.
 
Still, despite not appreciating the libations, I find London Grill to be about the perfect place to while away a few hours on a fine Friday afternoon.
 
April 07

And Speaking of Fencing...

...the 11th annual Ann Arbor Duelist Tournament will be held on August 23, 2008. Details to follow.

And It Just Keeps Getting Smaller

Way back when, I wrote:
 
Job interview advice for programmers
When you explain to the interviewer at the new company that you're looking to work with new technology because the system at your current company is so well architected that there's just no reason for them to switch from the old technology, it always helps when the interviewer turns out to be the former architect for the current company.

It's a small world, after all...
It's a small world, after all...
It's a small world, after all...
It's a small, small world...
Tomorrow, that interviewer and architect -- who has also been my boss for the last 14 months -- leaves for a new job in Indiana.
 
Today I learned that when he was at U of M in the middle 80s, he fenced at the Ann Arbor YMCA with the Ann Arbor Sword Club, taught by the illustrious David Hoornstra. (And no, there's no sarcasm there at all. I think David's truly a gentleman and a scholar.) I didn't fence at the time; but my roommate and best friend and eventually best man at my wedding fenced at the Y with the AASC.
 
A decade or so later, after he had long since moved on, I got a job in Ann Arbor; but we kept our house in Hopkins, and I commuted home on the weekends. That left me time to kill during the week. So I went to the Y and signed up for fencing classes, which were taught by the last of David's students still at the Y. For reasons still unclear, a large number of us showed up to learn fencing that session; and we formed a group that lasts to this day, through various changes in membership. And that group, the Ann Arbor Dueling Society, still takes pride in our "ancestral" ties to the AASC: if they had not existed, we would not exist today, and they're always welcome on our strip. And many of us have had the privilege to both study under David and meet him on the strip.
 
And as for my soon-to-be former boss: I studied where he studied, worked where he worked, and fenced where he fenced. Makes me wonder if a trip to Indiana is in my future...
 
It's a small world, after all...
It's a small world, after all...
It's a small world, after all...
It's a small, small world...
 

Hoody-hoo!

I tought this was pretty cool: McDonald's has WiFi at many of their locations. Yeah, there's a monthly fee; but since there's one only 5 miles from my house, and since I can't get an affordble high-speed connection of any sort at home, this seemed like a good deal.
 
But this week, I learned that Burger King has free WiFi. And there's one right next to the McDonald's near me.
 
Hey, McDonald's, guess what I'm having for dinner this week?
March 19

The Department of Motor Vehicles and Clipboards

All right, I've had enough. It's time for me to issue a decree:
 
Henceforth, programmers who wish to use the clipboard must be licensed in the same fashion as automobile drivers are licensed by the Department of Motor Vehicles. (Yes, yes, we call it the Secretary of State's Office here in Michigan; but more people know it as the DMV.)
 
1. Before you may use the clipboard to copy code, you must take 20 hours of classroom instruction on how not to use your clipboard.
 
2. Before you may be fully licensed to use your clipboard, you must undergo a six-month probationary period during which you may only use the clipboard with a grown up, licensed programmer observing your use of the clipboard.
 
3. Upon completing your probationary period, you may apply for a clipboard license at your nearest Department of Responsible Programmers. There your code will be examined for any signs of clipboard abuse. (Note: Unlike the tests at the DMV, this examination will not be easy. It will be brutal. You have been warned.)
 
4. If your code is deemed acceptable by a Responsible Programmer, you will receive a clipboard license, and be authorized to copy code as needed.
 
5. At any time, your code may be inspected for clipboard abuse. You will receive one (1) point for each line of unjustified code copying. If you accumulate 100 or more points, you will have to return to Clipboard School, or lose your license.
 
6. If at any time you accumulate 200 points, your clipboard license will be immediately revoked. You will be eligible to reapply after 1 year.
 
7. If at any time you accumulate 500 points, you will be shot. While we know this is harsh, it's the only economical option. We can't afford the cost of maintaining your code.
 
8. Clipboarding while drunk is grounds for immediate revocation of your license.
 
Yes, this means you!
 
March 03

I think they've been sampling their wares a bit too much

I like cheese. Practically any kind. Hard, soft, sharp, mild, smoky, creamy, stinky... I like cheese.
 
I hate alcohol. Nothing moral about my dislike, I just can't stand the taste. Whenever someone tells me, "Oh, you'll like this. It's different," it all tastes like beer to me -- or like whatever that taste is in beer that makes me hate beer. I can tolerate wine, but it still tastes like beer.
 
So when I saw Purple Moon from Fiscalini Farmstead, I was torn: good cheddar, soaked in cabernet. Now I've had meals cooked in wine or beer before, and the cooking process boiled off the alcohol. The taste I hated was gone. So the question was: would cheese soaked in cabernet taste good, or taste like (blech!) alcohol. I had to find out.
 
Well, when I opened the package, one whiff answered my question. I let a coworker (someone who actually drinks alcohol, so he has more experience than me) take a smell; and his response was, "That's strong!"
 
So then I wondered whether it was even any good or not. I mean, cheese and wine are both supposed to age, so it can't go bad, right? But still, alcohol usually smells spoiled to me; and this smelled spoiled.
 
So I checked the expiration date; and that's when I wondered if the fine folks from Fiscalini have perhaps been sampling the Purple Moon a bit too much: "BEST BY 02/30/08".
 
P.S. Actually, Purple Moon is some mighty fine cheese. I can't taste the alcohol at all. But I sure can smell it!
 
February 11

Blacklists are worse than spam

Spam wastes the time it takes to hit the Delete key. Blacklists stop legitimate business messages between individuals, and can cost real money. Blacklists are worse than spam.
 
If you're using an email service that relies on a blacklist -- and that includes you people using Yahoo.com -- and you stop getting email from me because some idiot at some T-Mobile hotspot was sending spam and Spamhaus decided to block the whole hotspot to stop the one idiot, it ain't my problem any more. Dump Yahoo and get a provider who doesn't use a blacklist.
 
February 09

If a Picture is Worth 1,000 Words, What Are Three Pictures Worth?

Answer: 85%, we hope. Or at least a good chunk of it...
KevinAndMartinHaveNoLives
 
KevinAndMartinDiscoverTheCommons
 
TheDesignCommons
January 21

Ink in 60 Seconds at the January MDSM

This Thursday, I'll be presenting Ink in 60 Seconds 2.0 at Microsoft Developers of Southwest Michigan. If you plan to attend, please RSVP to Contact@DevMI.com, so we'll know how much food to order. A description follows...

Ink in 60 Seconds 2.0

So why aren't you writing Tablet PC applications with .NET yet?

Do you think it's too difficult? Do you think you're too busy to learn the Tablet PC API? Well, Martin says you're wrong.

Or do you just not see what sort of Tablet PC app you might build? Do you think that there's no great Tablet PC applications out there for you? Well, Martin says you're wrong again.

And Martin's so sure you're wrong, he's going to prove it to you by building some simple little Tablet PC samples -- samples you can easily adapt into your own applications -- each written in under 60 seconds.

Then after each sample is running, he'll explain to you what he did, how he did it, and how you might expand on it. Some of the samples he'll build include:

  • 60 Seconds to Ink: Capturing Ink in a window in your application.
  • 60 Seconds to Ink Anywhere: Capturing Ink in any window in your application.
  • 60 Seconds to Programmatic Ink: Adding Strokes programmatically to an Ink surface.
  • 60 Seconds to Saving Ink: Saving your Ink to a file.
  • 60 Seconds to Loading Ink: Loading your Ink from a file.
  • 60 Seconds to Saving Some Ink: Saving part of an Ink image.
  • 60 Seconds to Loading Some Ink: Loading Ink into an existing image.
  • 60 Seconds to Exporting Ink: Saving Ink as a bitmap.
  • 60 Seconds to Selecting and Resizing: Manipulating the Ink that you draw.
  • 60 Seconds to Erasing: Erasing the Ink that you draw.
  • 60 Seconds to Drawing Attributes: Drawing Ink in multiple colors and pen shapes.
  • 60 Seconds to Clipboarding: Copying and pasting Ink.
  • 60 Seconds to Simple Handwriting Recognition: Simple handwriting in a form.
  • 60 Secondes au Français: Handwriting recognition in another language.
  • 60 Seconds to More Handwriting Recognition: Handwriting recognition mixed with typing.
  • 60 Seconds to Handwriting Recognition Anywhere: Handwriting recognition from any Ink surface.
  • 60 Secondes à Plus Français: More handwriting recognition in another language.
  • 60 Seconds to Gestures: Ink shape recognition.
  • 60 Seconds to Text-to-Speech: A simple talking application.
  • 60 Seconds to Speech Recognition: A simple voice-command application. (New for this presentation!)

And just in case those samples don't inspire you to devise a great new Tablet PC application, Martin will finish the presentation by spending 60 seconds (probably more) describing each of ten different killer Tablet PC applications that he's just too busy to write himself, but which he thinks somebody should be writing.

January 20

Dr. Strained Memory or: How I Learned to Stop Worrying and Love Compact Framework Memory Management

OK... So why has my DODO been incalculable? Well, because we've been chasing down memory problems in our .NET Compact Framework 2.0 app that runs under Windows CE 5.0.
 
And if that just sent a chill down your spine, then you've probably been here before. You have my sympathies.
 
If you haven't been here before but you're planning a CF/CE app: Be afraid. Be very afraid.
 
The following is a brief summary of what we've learned (the hard way) about memory management in a Compact Framework application. 

"In the beginning, the Universe was created. This made a lot of people angry, and has been widely regarded as a bad idea."

My client's application comes in two versions: one that runs on a laptop, and one that runs on a handheld computer running Windows CE 5. Since both versions run .NET -- .NET Framework 2.0 on the laptop, .NET Compact Framework 2.0 on the handheld -- they figured to share a lot of code between the two platforms, including a homebrew implementation of a Model-View-Presenter architecture. The implementation of View (and Presenter, to a lesser extent) had to change across platforms; but for the most part, what was a good architecture for the laptop was seen as a good architecture for the handheld.
 
First mistake, there...
 
And although I wasn't here when that mistake was made, I probably would've made the same mistake myself. I didn't realize that on the handheld platform, you need different coding priorities.

"Do you know what the secret of life is? This. One thing. Just one thing. You stick to that and the rest don't mean ****."

When you code, the quality of the result depends significantly on your priorities: what do you want from the code? Every developer has an idea of the "correct" coding priorities. Some value small code, or fast code, or readable code, or clever code. Steve McConnell once advised deciding and announcing your priorities for a given project before work begins, so everyone knows what's important for this project. You might make a prioritized list, such as:
  1. Correctness.
  2. Maintainability/readability.
  3. Speed.
  4. Extensibility.
  5. Efficient use of memory.
  6. Schedule.
  7. Modularity.
  8. Reusability.

And so on. Just let the team know what's expected from them, and you're more likely to get it from them.

But for many teams, that list is too much bother. They can get by with a simple mantra:

Make it run.

Make it right.

Make it fast.

Make it run, so users can give you feedback. Make it right from their feedback. And then optimize only when necessary to make the users happy, because optimization can be difficult to read and maintain and is prone to bugs.

Well, we've learned a new mantra for the handheld:

Make it small.

Make it run.

Make it right.

Make it fast.

Repeat, repeat, repeat...

You have to make it small first; because on CE 5, if it's not small, it will never run right, and it will be fast only in crashing. And then, when you take steps to make it run and right and fast, you'll inevitably make it larger, and risk crashing due to that.

So on CE 5, you have to design for small first. Adding small afterward is a great way to push your DODO to Infinity. I should know.

"A Man's Gotta Know His Limitations."

So here's the short summary of what we've learned about our limits. First, keep in mind that this code comes in two general types: Native, and Managed. Native Code is code compiled directly for the platform, and responsible for managing and allocating its own memory and other resources. Managed Code is .NET Compact Framework code, which runs inside the Common Language Runtime, a Native Code "shell" that loads and runs and manages Managed Code. It takes care of allocating memory; and if -- if -- you let it, it does its darnedest to clean up that memory when you're done with it. And Managed Code may very well load and call Native Code for certain purposes. (Native Code can load and run Managed Code as well; but for this discussion, that's irrelevant.)

Some of what follows applies only to Native Code. Some applies only to Managed Code. And some applies to both.

"I want to be an explorer, like the Great Magellan." "Oh, you're too late! There's nothing left to explore!"

CE 5 uses Virtual Memory and memory mapping to give each running  process a "private" memory space. I'm no memory management guru; but as best I understand it, this means that each process thinks it "owns" the machine. The Operating System (CE 5) maps into part of that memory space. The app and all its data map into another part. On handheld devices, memory is usually pretty limited (128 MB on board, in our case, and 1 GB on card), and probably less than the addressable space in a process's memory map.

The OS itself loads into a given memory location. I can't say where, because I'm not a memory guru. I'm trying to give an overview here, not details. But the important part is that your process then receives an address space in which your process lives in the space from 0 GB to 1 GB, and "global" storage lives in 1 GB to 2 GB. The OS lives beyond that space.

"Game over, man! Game over!"

OK, so your process's memory map lets it address 1 GB (between addresses 0 GB and 1 GB); but here's the kicker, and here's where our troubles began. The actual memory accessible to your app -- also known as the Virtual Memory, i.e., the chunk of memory mapped into that 1 GB space -- is restricted to 32 MB on Windows CE. Period. No matter what you do. If your app needs more than 32 MB to store your currently loaded code and data, that's it. You're gonna crash. In our case, we didn't crash; but we made calls to SQL Mobile in a low-memory condition, and it'll crash like clockwork, every time.

So that's simple, right? Stay under 32 MB, right? What kind of freakin' handheld app needs 32 MB, anyway?

Well, one that was ported from the laptop without sufficient consideration for Make it small, make it run, make it right, make it fast, that's what kind.

And oh, if only it were as simple as waving a magic wand and saying "Keep it under 32 MB"...

"Take your stinking paws off me, you damned dirty ape!"

Maybe, maybe you can find a way to do what you need within 32 MB. (Probably not: when you tell customers that they're getting portability as a tradeoff for power and features, they never hear the tradeoff part. They'll want your handheld app to be portable and as powerful as your laptop app and as fast. Learn to tell them "no" as early as possible.)

But you're not the only one who gets to use that 32 MB. No, in fact, every app in the system has its stinking paws on your 32 MB, including the OS!

See, when an app is actively running on the handheld, its Virtual Memory is mapped into a special reserved 32 MB slot in the system, slot 0. Your app itself is loaded at the bottom of slot 0, growing up. Any unmanaged DLLs it loads are loaded at the top of slot 0, growing down as each is loaded. (Each DLL is allocated space in 64K chunks, so DLLs that are close to 64K in size -- or 128K, or 192K, or... -- are loaded most efficiently.) And the space in between is available for your app's data. You can also store data in the "global" area from 1 GB to 2 GB; but that's a lot more difficult to use, so you don't want to if you don't have to.

But here's the tricky part: because handhelds have limited memory, CE 5 optimizes the memory used by DLLs. If a DLL is loaded in one app, CE doesn't load it into another app that also uses it. CE loads it once, period. But in order to do this, CE loads the DLL into the same location in every app that uses it -- and effectively, every app that doesn't use it. The unmanaged DLLs are loaded into the top of slot 0 itself, and just left there as different apps are mapped into slot 0 and back out again. So your app takes the hit for every unmanaged DLL loaded anywhere in the device. That can even include OS DLLs: if the OS runs out of room for its DLLs in its reserved memory, it loads them into slot 0. (In our case, after the vendor did some tuning, that only meant one unmanaged DLL loaded into slot 0 by the OS itself.)

"Invention, my dear friends, is 93% perspiration, 6% electricity, 4% evaporation, and 2% butterscotch ripple." "That's 105 percent."

Now if the 32 MB limit sounds scary, and the external DLLs chewing up your 32 MB sounds even scarier... Well, you're right, they are scary.

But before you set out to try to work around them, ask yourself one thing: are you using .NET Compact Framework 2.0 (or later)? Because if you are, then the CF team has already given you an invention where they put in the perspiration, electricity, evaporation, and butterscotch ripple. Sadly, it's not a 105% solution (more like an 80% solution in our case); but it's very likely better than you have time and resources to devise and implement and test and maintain yourself. So before you start jumping through hoops, let's look at the hoops they've already jumped through for you.

When you build a .NET app (Compact Framework or regular Framework), the real application is the CLR itself. It's the thing that runs, not your code; and then it loads your code, and uses your code to tell it what to do.

So what this means on the Compact Framework is that the CLR can be smart: it knows about the 32 MB limit, so it works overtime to try to get around it. The biggest technique it uses is that all of your Managed DLLs and your managed application are loaded into the global storage area between 1 GB and 2 GB. Then, as you call the code in your app and your DLLs, the CLR loads the pieces you use into an area within your 32 MB VM. This JIT (Just In Time) Heap starts at about 1 MB, and grows as needed; but if the CLR sees that memory is low, it "pitches" code out of the JIT Heap, keeping only the more recently used code. So the JIT Heap can be treated as a 1 MB block under normal circumstances.

And another way in which the CF CLR is smart: if any one object you allocate is larger than 2 MB (or it might be 1 MB, I'll need to check), it automatically allocates from the global storage, without making you jump through all the hoops involved. The CLR knows how to jump through the hoops. That's its job.

If you think you can write better memory management than the CLR provides, be my guest. Be sure to allow lots of time in your schedule for design, redesign, implementation, testing, fixing, retesting, refixing, reretesting, reredesign, nervous breakdowns... Now CLR memory management does not come without a cost, of course: the CLR itself requires another 1 MB block out of your VM. And other data used by the CLR can add up as well, in the form of different heaps:

  • The AppDomain Heap describes the assemblies, modules, and types used by your app. The CLR uses these to find and load and decipher code as you call it. It grows as the overall app+DLLS grow.
  • The Process Heap and the Short Term Heap are memory used and discarded by the CLR as it works. These are usually small, usually transitory, and pretty much always beyond your control.
  • And finally, the GC (Garbage Collected) Heap itself, where the CLR allocates all of your data (other than large allocations stuck in global storage). Anything in here can be released by your code at any time, and the CLR will Garbage Collect it to free up space when it sees a need.

So your real limit in a Managed app is: 32 MB, minus the size of Native DLLs in slot 0 (in our case, 5 MB, mostly due to SQL Mobile), minus 1 MB for the CLR, minus the sum of all the heaps (with a minimum around 2 MB). That's how much Native data you can afford. Because remember: your Native DLLs will allocate memory in your 32 MB VM as well.

And frankly, for many sorts of handheld apps, that's a lot. But for anything ambitious, anything that really makes customers excited... That's not enough.

In testing of our app (explanations below), the JIT Heap, the AppDomain Heap, and the GC Heap have climbed to nearly 13 MB. Add in 5 MB for Native DLLs, 1 MB for the CLR, and 1 MB for the Process and Short Term Heap, and we're up to 20 MB out of 32. That's enough to make me nervous. And for large SQL Mobile queries, that may be enough to crash. (SQL Mobile usually crashes when we make a large query with less than 2 MB VM free; but we once saw it crash with 3.4 MB free.)

"No. Try not. Do... or do not. There is no try."

So now you know the CF 2.0/CE 5.0 memory landscape. You know, kind of, what your limitations are.

So if your app starts crashing and memory errors seem to be the diagnosis, you need to throw out stuff that might waste memory, right?

No. Wrong. Stop. Remember this important mantra: We're not guessing, we're profiling.

With a lot -- a lot -- of experience, you can begin to guess where system performance problems are, and be right maybe half the time. (And by performance, I include memory usage, CPU usage, and other ways your app might bog down a machine.) But people with that much experience will usually tell you: don't guess, use a profiler.

Now on the laptop, there are many profiling tools available. On CE 5, not so many. One of the best we could find is the .NET Compact Framework Remote Performance Monitor. (That's a link to the CF 3.5 Power Toys from Microsoft; but the RPM in there works fine with CF 2.0.) This tool will tell you the size of your different heaps. It will also take "snapshots" of your GC heap, which will let you see how many objects of different classes are in use, and how much space they consume. (In our case, the worst offender is 14,408 Strings, requiring 0.89 MB of storage. The top 10 classes for memory usage consume over 2.6 MB out of a 3.3 MB GC heap. I won't know why until I do more research. I have my guesses, but we're not guessing, we're profiling.)

Another useful memory profiling tool is DUMPMEM. (This is targeted at Pocket PC 2002, but still works OK for CE 5.) This tool is a bit verbose, with a lot of nearly unreadable information; but near the end of the report, it spells out all of the apps running on your device, including which unmanaged DLLs each has loaded.

Beyond those, we found it easiest to write our own profiling tools. They're crude, but they helped us match memory usage to user activities in the application. They rely heavily on the MemoryManagement class from the OpenNETCF libraries.

"Tweaking? A project that needs tweaking?"

Finally, some general lessons we learned about memory management under CF 2.0 and CE 5.0:

  • Design for small from the start. Don't try to add it later. Yes, I repeat myself. It bears repeating.
  • We're not guessing, we're profiling. Yes, I repeat myself. It bears repeating.
  • Don't waste time trying to "tweak" your way to sufficient memory. Tweaking is usually a sign that you're guessing, not profiling. We did a lot of little tweaks that saved us a few K here, a hundred K there... Those all made some difference, but at a lot of cost; whereas finding and eliminating the 14,408 cached strings will probably make the difference we need. When you try to tweak to fit, it's like Human Tetris: you might twist yourself into exactly the right shape; but if you're wrong, you won't know it until you go splat! Instead of tweaking, profile, identify and locate the major leaks, and fix them. Repeat, repeat, repeat.
  • Build memory diagnostics in from the start. You'll curse me now. You'll thank me later.
  • Graph your diagnostics, and identify on the graphs what the user was doing at each major change. That will help you in locating the major leaks.
  • Don't try to outsmart the CLR and the GC. Maybe you are smarter, but do you have time to build and test and maintain your smarter solution?
  • Sometimes, when your code is leaking, it can appear that the GC is not collecting. It is, at least as much as it can, and I have the graphs to prove it. Trust the GC.
  • Never call GC.Collect() directly. It never helps -- never! -- and it often hurts. It never helps because the GC is optimized to not waste too much CPU time. If called, it doesn't do any real garbage collection until a trigger has happened: cumulative Managed allocations have passed a megabyte boundary; GDI+ resources (pens, fonts, brushes, etc.) are used up; or memory is used up. If none of those have happened, no garbage is collected. But it may hurt, because before testing the triggers, it suspends your whole app, including waiting for each thread to reach a "suspendable" state. So though calling GC.Collect() won't save you any memory, it can cost you time.
  • Maybe call the unmanaged heap compact API. This seldom has had any effect for us; but on rare occasions, it has reclaimed some Virtual Memory for us. We're still kind of undecided.
  • If you can, wait for CE 6.0. It has a radically expanded memory mapping scheme, including 2 GB of VM per process. If that's not enough, you don't understand that the "C" in "CF" and "CE" stands for "Compact", as in "tiny". If 2 GB is too tiny for you, you're on the wrong platform. But as of this writing, there are no production devices running CE 6.0.
  • Consider this: is a UMPC compact enough for your customers? It's small. It's portable. And it will run the same code as your laptop does. (For us, the answer is no; but maybe you'll have a different answer...) 

"Think it'll work?" "It would take a miracle."

Actually, no, you won't need a miracle to live within the memory limits of CF 2.0 and CE 5.0. You'll just need awareness, design, profiling, patience, perseverance, and maybe a little bit of luck. And maybe I've given you a few more rabbits for your hat.

 

So Where've You Been, Martin?

So why no new posts recently? Well, remember the DODO? Well, mine can't be calculated for 2008 yet. You can't divide by zero.
 

Indescribable

OK, this is just... indescribable. I mean, I can try to describe it; but you gotta see it to believe it. An animated Dean Koontz speaks to the animated spirit of his dead Golden Retriever, Trixie. And then, after their conversation, their heads and eyes follow your mouse around. Just too weird...
 
Despite a site so weird it freaked me out, Mr. Koontz has another winner with The Darkest Evening of the Year. It has everything. Dogs. Hit men. Dogs. People with secrets. Dogs. Second Life. Dogs. Really nasty people. Dogs. Really good people. Dogs. Private detectives. Dogs. Guns. Dogs. Dead nuns on the telephone. Dogs. Strange messages from somewhere else. Dogs. Explosions. Dogs. And mysterious creatures who know things you don't (in other words, dogs).
 
Mr. Koontz doesn't like to be pigeon-holed in a genre. That's too bad, because I'm going to do it anyway. And it's not the genre he is most often placed in (i.e., horror). No, based on what I've read (which is by no means all of his works), I would say he most fits in fantasy. But not fantasy as it has become: a genre mostly dominated by Professor Tolkien and his peers and imitators, with swords and sorcery and monsters. No, Mr. Koontz simply writes of a modern world where fantastic things happen, large and small. In fact, the small are the most common. It just happens that since some fantastic things can be terrifying or incomprehensible, the books get pigeon-holed as horror. But it's not horror like Stephen King writes horror. It's more just "The universe is a much more mysterious place then you realize, and you're about to get a glimpse of that."
 
This isn't the best book Mr. Koontz has written. I think his Odd Thomas series is hard for anyone to top, him included. And Life Expectancy has to be the most eclectic mix of fantasy, prophecy, humor, baking, circus clowns, and acrobats ever assembled. But this is a really strong addition to his library.
 
Especially if you like dogs.
 
December 30

Interfaces

OK, along with the Clipboard, there's another habit I'm finding to be overused: interfaces.
 
And while I'm not going to go as far as I did with the Clipboard ("No, no, no, no, no, no, no, no, NO!"), I am going to say...
 
Stop. Think about it. What does an interface gain you here, anyway?
 
As a reminder: an interface is a set of methods, properties, and events that you can define separate from any class. Then one or more classes can be written to provide those methods and properties and events, and one or more classes can be written to use those methods and properties and events, without any of those classes knowing any of the details of each other. They just know how to ask for work to be done, not how the work is done nor even what's doing the work.
 
The principle -- and the benefit -- is called Loose Coupling. It allows you to more easily change how the work is done or how the results are used, because neither side of the relation knows anything but the interface.
 
Implicit in that benefit is the word "coupling", meaning a pairing between provider and user. With interfaces, it's pretty easy even to change the interface provider to another provider entirely, without the user ever knowing. It's also pretty easy to have different users, without the provider ever knowing.
 
But sometimes you have to ask: "How many couples will I have here?" And if the answer is, "One, as far as I can foresee," then the interface really gains you nothing. If you're never going to change to a different provider or a different user, then you can just as easy work with the provider class instead of a provider interface.
 
"But does it make any difference?" you ask. Yes. Absolutely. An interface plus a class means roughly double the maintenance effort as the work changes. It also makes it much harder to navigate and search the code. I'm working on a system right now with 15 client classes that use 15 interfaces to talk to 16 service classes. Yes, 15, 15, 16. That's because in 14 of those cases, exactly one client uses exactly one interface to talk to exactly one service. In only one of those cases are there two possible services that the client can talk to. That one benefits from an interface.
 
Meanwhile, every time something has to change in the conversation between one of those clients and one of those services -- because they are far more tightly coupled than the designers might have hoped -- it has to change in three places: the service has to add a new method, property, event, or parameter; the interface has to add the new method, property, event, or parameter; and the client has to use the new method, property, event, or parameter.
 
And on top of that, any time I start from the client and search for a given method, property, event, or parameter, I have to do extra searching: I can't just use Visual Studio's "Got to Definition" function, because that will take me to the interface, not the implementation. Instead, I have to use Visual Studio's "Find All References" function, and then search through those references until I find the implementation.
 
There are other benefits of interfaces besides loose coupling. Interfaces do let you hide details of your class and expose only what you want clients to know. But if you don't need to hide internals, and you've only got one possible coupling, then Stop. Think about it. What does an interface gain you here, anyway?