Wednesday, January 30, 2008

WPF Set: Now in 3D!

I last discussed Set about 3 weeks ago. At the time, my implementation was based on buttons. It worked fine, but when I saw how it looked on a friend's machine running the 'classic' theme I was appalled.

I got thinking: there has to be a way to make this game more interesting.

The answer: 3D and gratuitous animation.

The address for the XBAP hasn't changed: http://j832.com/workBlogFiles/WpfSet/

WPF Set - 3D!

The source code has been checked-in to my SVN repository. The code files actually live under J832.Wpf.BagOTricksApp, but you can build and play with the stand-alone app by loading the J832.WpfSet solution file. (Thank you, CSProj file linking feature.)

Cool stuff:

  • The listbox on the right that displays the matched sets now uses AnimatingTilePanel.
  • First use of the new WPFUtil class, which exposes a set of Animate methods. These basically formalize and abstract my simple attraction-based physics model. I support 1-dimensional (double), 2-dimensional (Point/Vector), and 3-dimensional (Point3D/Vector3D) animation. Check out ZapScroller and AnimatingTilePanel in the source to see the other places these are used.
  • I've also added some helper extension methods to WPFUtil. Very useful.
  • Implemented a couple of super-simple 3D components: ButtonBase3D and ToggleButton3D. An interesting exercise. Hoping to move FlipTile3D to these in the future.

Not cool stuff:

  • Keyboard accessibility has evaporated. With the previous implementation, you could tab around to the buttons and press spacebar to select/unselect a "card". More work than I signed up for in this iteration, but something to keep in mind.
  • WPF handles z-order great in 3D unless you have transparency in your textures. Take a look at the corners of raised cards. Very frustrating. The only work-around is to manually re-order the child elements. Lame.
  • Perf is great...on my super fast workstation. Even on my relatively beefy laptop, I notice some glitching when things are moving around. Ideally, I'd detect machines hardware limitations and degrade the animations. I should probably offer a "turn off the fancy stuff" check box. Eh, V3.

This will of course be included in the next drop of the full bag-o-tricks, but I thought it was cool enough to share out-of-band.

Have fun.

Sunday, January 27, 2008

Improving NotifyWorker (and why blogging makes me smarter)

My current day job consists of writing middleware and web-based LOB software for an actuarial services company.

David is my primary collaborator and a fellow blogger. We get along amazingly well, but every once in a while, we disagree. The amazing thing, though, is how we handle disagreements.

I'm at a point where I look forward to disagreement! For a reason that I hope more people can come to realize.

If we disagree about how something should work, it's almost always an opportunity for improvement. Specifically, at least one of the following is likely to happen:

  • I get smarter
  • He gets smarter
  • The code gets better

Quite often, it's all three. I know this sounds like motivational speaker talk or corporate training fodder, but it's true. The fact that we often discuss our disagreements with explicit reference to masters is also helpful.

I blog for similar reasons. I'm far from a CLR, C# or WPF expert, at least relative to the experts I've had the opportunity to work with.

I'm just a geek trying to figure things out and sharing as I go. Hopefully what I share is helpful. Often, though, blogging has self-serving benefits. Just taking the time to write down explanations for what I'm doing forces me to rationalize edge cases.

If I had never blogged the recursive flattening craziness, I would have never have seen all of the edge cases I had missed the first time out.

Anyway, to my point.

Simon was kind enough to point out a deadlock in my NotifyWorker code.

FYI: At this point, looking at the code will be quite helpful.

I was doing a Thread.Join() in the middle of a lock. Of course, if the thread in question is waiting on the lock which is held, the thread will never exit. The result: the Join() call will never return.

Deadlock, indeed.

Props to Simon for pointing out this problem.

I moved the Join() outside of the lock and thought I'd fixed the problem.

Maybe, but I also realized another problem.

  • Dispose is likely called from the UI thread.
  • Dispose calls Join on my worker thread as discussed above.
  • The worker thread does Dispatcher.Invoke twice.

What happens if Dispose is called between my check for m_disposed and when the Invoke actually gets to the UI thread?

Dispose will be tying up the UI thread waiting for Join() to return. The worker thread will never terminate because it's waiting for Invoke to get to the UI thread.

Deadlock again.

Darn.

The solution: Move from Dispatcher.Invoke to Dispatcher.BeginInvoke.

BeginInvoke returns an instance of DispatcherOperation. This class has an Abort method which can be used to abort a pending BeginInvoke.

I now have an instance field containing the pending operation, if one exists, which can be aborted via Dispose before the call to Join. I also now enforce that Dispose must be called on the UI thread (by adding a call to VerifyAccess). This ensures that Abort is not called while the worker is synchronized to the UI thread.

After some careful uses of DisaptcherOperation.Wait and some paranoid null checks, I think I'm okay. 

As an aside, I also noticed that Dispose() will throw in the case where NotifyNewWork() has never been called. I fixed that, too.

*Sigh*

Threading code is tough. I had to stand up and pace around a few times as I mentally worked through possible edge cases.

As I've said before, I think this implementation is better, but it would be a stretch for me to claim it's correct. Hopefully, it's more correct.

Please keep the questions, comments, and feedback coming (after you take a look at the post about contacting me).

The code will get better and we'll all get smarter.

 

Happy hacking.

Saturday, January 26, 2008

Oleg, what's your email? (Contacting me via my blog.)

This has happened a few times, so I thought it would be worth mentioning.

  1. I love comments. I try to blog more than "check out this link" posts. It takes a bit of work. Knowing folks are reading is great. But...
  2. If you're saying more than "interesting post"--if you have comments or questions--please make sure I have a way to contact you.

Oleg Mihailik made an interesting comment about my NotifyWorker post:

As long as you are already using the delegates, you can use closures (local variables) instead of creating artifical types to hold them.

Then you'd have to provide 2 parameterless delegates: one for work item and another for 'OnCompleted' logic on GUI thread.

That simplifies out the packaged parameters' class, AND eliminates the exception catching work by design.

If they care enough to handle exceptions, they'd do it in conventional and readable way: by enclosing the dangerous part in try/catch. And then, they can reflects it in exactly the same 'OnCompleted' delegate.

I have questions for him and I have no clue how to drop him a line.

If you'd like to chat (or talk job offers) please send me an email.

My obfuscated address--edeya9902(at)sneakemail(dot)com--in the left pane, is meant as a test. If you can't figure it out or don't want to go through the effort of doing the manual copy-paste-replace, we probably shouldn't chat.

Or if you post a comment, just make sure you link back to a blog with a contact page. That's more than sufficient.

Thanks.

Tuesday, January 22, 2008

Responsive UI with Unresponsive Data: NotifyWorker

Yes, I finally got off my SelectRecursive kick. This is penance.

The 3-box Visio Diagram

How many user interfaces do you design that follow this pattern?

image

Okay, almost all of them.

A frequent refrain from users (well, at least me):

Regardless of what you're doing behind-the-scenes, the interface should never hang, stutter, or lag. Ever.

Easily said, right?

Well, while hacking on one of my side projects, I ran into this problem.

I put on my "framework guy" hat and asked, "Can I formalize this into a pattern?"

My answer: NotifyWorker.

Now before I get into NotifyWorker, I should mention BackgroundWorker: a frequently used and well thought-out component supplied by our friends in the Baseclass Library (BCL) for this kind of thing.

The trick performed by BackgroundWorker is simple, but important: allow start/stop/cancel of a task on another thread. It also keeps developers sane who have to deal with strict rules about what can only be done on the UI thread.

The type of tasks for which NotifyWorker was designed fit into a special niche that I think BackgroundWorkre misses:

  • Tasks that are long enough to lag the interface (0.1+ seconds) but are too short to require tracking of percent complete (so shorter than, say, 5 seconds).
  • Tasks that are repeated constantly as the UI updates. Think of recalculating a math/physics model or checking a server-hosted word list for a type-a-head find control.
  • Tasks where the work to be done is--in relative terms--longer than the work to update the user interface. If the task takes 0.1 seconds, but updating the 1,000 controls in your window takes 2 seconds, you should start by tweaking your architecture before using NotifyWorker.

How does it work?

(Reflector is how I learn all of my new APIs.)

image

The constructor takes three parameters that outline the diagram above and the workings of NotifyWorker:

  • Func<bool> prework: this is a delegate that is called on the Dispatcher (UI) thread in a WPF application. Delegate passing is a trick I use a lot, and you should, too. The method does the work to take interesting parameters from the UI (control values, etc.) and puts them in a spot where NotifyWorker can safely play on a non-UI thread. If you decide there is nothing interesting to do, you can return false, telling NotifyWorker "never mind".
  • Action work: this is where the magic happens. This function is called on a background thread which will leave your UI nice and responsive. Be super careful that 'work' only touches state (fields, etc) that you've safely set aside during prework.
  • Action postWork: the last box in our diagram. It takes the work done in 'work' and updates the UI accordingly. This method, as well as 'preWork', synchronizes the UI and background threads, so you don't have to worry about locking.

How do you kick things off? Call NotifyNewWork. This method can be called often, if you want. Put it in the 'Changed' handler of your favorite Slider or TextBox. If NotifyWorker is idle, it will wake up and immediately call preWork. If NotifyWorker is busy, it'll loop right around to get new input values as soon as postWork is done.

A demo

image

Sexy, huh?

The scenario is simplistic and contrived, like so many good demos.

Both sets of UI do the same thing: take the values from two sliders and sum them. Not too complicated.

For some strange reason, the sum 'routine' takes 0.25 seconds to return a result.

Maybe it's that new math...

Eh, it's probably the Thread.Sleep(250) I put in the method.

Anyway, use your imagination. You'll notice that the 'slow' UI is, well, slower. It lags a bunch as you drag the sliders since it's calling the expensive sum method on the UI thread.

The NotifyWorker controls do much better because the expensive call is hidden off-thread.

Simple, but useful.

Odds and ends

You'll notice a LastClientExceptionEventArgs property and a ClientException event. These are designed to make it a bit easier to handle non-critical exceptions during 'work'. The demo code actually shows this off pretty well.

You'll also notice that NotifyWorker implements IDisposable. Dispose will make sure to end any background work when you're done with NotifyWorker.

Under the covers, NotifyWorker uses LockHelper and some of the pulse/monitor tricks I wrote about a few months ago.

That's about it.

Since NotifyWorker is hard-wired to the notion the Dispatcher, it lives in J832.Wpf.BackOTricksLib. The demo is in the Bag-o-Tricks app under NotifyWorker.

I'm not going to do an official release (zip with binaries/source) of the bag for this sample. It's cool, but not cool enough to warrant a whole new drop.

It also gives you an excuse to play with SVN, if you haven't already. You can always just manually download the code from my SVN share using your browser, too.

Let me know if this works well for you.

 

Happy multi-threaded hacking!

 

Note: I've had some funky auth issues with Firefox on the SVN server lately. Let me know if you have any trouble.

Saturday, January 19, 2008

SelectRecursive: If 3rd times the charm, 4th times a warning

I thought I finally nailed SelectRecursive--my Linq-friendly extension method for navigating homogenous hierarchies. In my infinite cleverness, I figured I could avoid paying the common call stack cost of recursive algorithms by creating my own stack.

The solution I posted Wednesday was an okay start of the philosophy, but I really messed up the implementation.

I thought I got it right yesterday, but after being bitten once, I was cautious--notice I said "Smart(er)".

Well, the implementation yesterday was certainly better, but it was missing a critical component: correct clean-up.

IEnumerator<T> implements IDisposable.

Why? Well, suppose you're enumerating over a database table. When one is done walking through the items, you might want to close your connection.

We rarely see the use of IDisposable in this context, because it's hidden behind the 99.999% use of IEnumerable<T>--foreach.

Don't forget that this:

foreach (object item in sourceEnum)
{
    // do something
}

Looks like this to the runtime:

using (IEnumerator<object> source = sourceEnum.GetEnumerator())
{
    while (source.MoveNext())
    {
        // do something
    }
}

Well, actually it looks like this:

IEnumerator<object> source = sourceEnum.GetEnumerator();
try
{
    while (source.MoveNext())
    {
        // do something
    }
}
finally
{
    source.Dispose();
}

foreach does the work of calling Dispose() on the enumerator--both when things go well and if there is an exception thrown in the while loop.

Since the "simple" version of SelectEnumerator I posted yesterday uses foreach, everything works great. Even if an exception is thrown deep in the recursion, the unrolling of the stack will go through all of the nested finally blocks.

The "smart(er)" version of SelectEnumerator will have to be smart to handle disposing every enumerator it creates--both when the stack is popped normally and in the case of an exception.

public static IEnumerable<TSource> SelectRecursive<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, IEnumerable<TSource>> recursiveSelector)
{
    Stack<IEnumerator<TSource>> stack = new Stack<IEnumerator<TSource>>();
    stack.Push(source.GetEnumerator());

    try
    {
        while (stack.Count > 0)
        {
            if (stack.Peek().MoveNext())
            {
                TSource current = stack.Peek().Current;

                yield return current;

                stack.Push(recursiveSelector(current).GetEnumerator());
            }
            else
            {
                stack.Pop().Dispose();
            }
        }
    }
    finally
    {
        while (stack.Count > 0)
        {
            stack.Pop().Dispose();
        }
    }
}

Take a look at the code from yesterday to see the diff.

At this point, I'm pretty nervous about saying I've gotten this "right". In all honesty, I did the stack flattening to see if I could do it and do it well.

As I've mentioned before, this pattern is only useful if you plan on having prohibitively deep hierarchies where the cost of the churning the runtime stack or the chance of stack overflow is high.

If neither is the case, keep things simple.

Remember what I said about clever.

 

Happy hacking.

Friday, January 18, 2008

Source code, HTML, and an Exercise for the Reader

No clue why I want to be vague about this. Probably because I'm late for a party, but really wanted to share.

And you're smart. You'll figure it out.

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="VS Copy-Paste to HTML" >
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <RichTextBox Name="m_richTextBox" TextChanged="m_richTextBox_TextChanged" />
        <TextBox Grid.Column="1" Name="m_textBoxHTML" />
    </Grid>
</Window>

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Web;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Media;

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void m_richTextBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        m_textBoxHTML.Clear();
        m_textBoxHTML.AppendText("<div style=\"font-family:monospace;\">" + Environment.NewLine);
        foreach (Paragraph paragraph in m_richTextBox.Document.Blocks.Cast<Paragraph>())
        {
            foreach (Run run in Decompose(paragraph.Inlines))
            {
                m_textBoxHTML.AppendText(toCleanedColoredSpan(run));
            }
            m_textBoxHTML.AppendText("<br/>" + Environment.NewLine);
        }
        m_textBoxHTML.AppendText("</div>");
    }

    private string toCleanedColoredSpan(Run run)
    {
        SolidColorBrush solidColorBrush = run.Foreground as SolidColorBrush;
        if (solidColorBrush == null)
        {
            return cleanString(run.Text);
        }
        else
        {
            if (solidColorBrush.Color == Colors.Black)
            {
                return cleanString(run.Text);
            }
            else
            {
                string colorString = solidColorBrush.Color.ToString();
                Debug.Assert(colorString.Length == 9);

                colorString = colorString.Substring(3);

                return string.Format("<span style=\"color:#{0};\">{1}</span>",
                    colorString, cleanString(run.Text));
            }
        }
    }

    private string cleanString(string source)
    {
        source = HttpUtility.HtmlEncode(source);
        source = source.Replace(" ""&nbsp;");
        return source;
    }

    private static IEnumerable<Run> Decompose(IEnumerable<Inline> inlines)
    {
        foreach (Inline inline in inlines)
        {
            if (inline is Span)
            {
                foreach (Run run in Decompose(((Span)inline).Inlines))
                {
                    yield return run;
                }
            }
            else if (inline is Run)
            {
                yield return (Run)inline;
            }
            else
            {
                throw new NotSupportedException();
            }
        }
    }
}

Recursion, Linq, etc. - 3rd Times the Charm

The joke about Microsoft is that it always takes them three times to get it right.

If you look at my posts on the game Set in WPF, it would seem I follow the same pattern.

Well, here I go again.

Let's start simple: I have a path to a directory and I want to enumerate over all of it's subdirectories recursively. To be super concrete:

string[] startPaths = new string[] { @"D:\j832_svn\PublicSoftware\" }; 
IEnumerable<string> subPaths = SelectRecursivePaths(startPaths);

Easy enough.

What's the scenario-specific implementation of SelectRecursive? Well, our friend System.IO.Directory provides what we need.

private static IEnumerable<string> SelectRecursivePaths(IEnumerable<string> paths)
{
    foreach (string path in paths)
    {
        yield return path;
        foreach (string subPath in SelectRecursivePaths(Directory.GetDirectories(path)))
        {
            yield return subPath;
        }
    }
}

This code does the job for doing an in-order, recursive traversal of all of all of the directories. But it isn't very Linq-ish, is it?

Getting Linq-ish: SelectRecursiveSimple

Could there be a way to extract out the call to Directory.GetDirectories such that this method could be used over any homogenous, hierarchical structure? Yup.

public static IEnumerable<TSource> SelectRecursiveSimple<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, IEnumerable<TSource>> recursiveSelector)
{
    foreach (TSource element in source)
    {
        yield return element;
        foreach (TSource subElement in recursiveSelector(element).SelectRecursiveSimple(recursiveSelector))
        {
            yield return subElement;
        }
    }
}

Now we change the call site to embody the call to GetDirectories:

IEnumerable<string> subPaths = startPaths.SelectRecursiveSimple(path => Directory.GetDirectories(path));

I love lambda expressions and extension methods.

With me so far?

Getting Clever: SelectRecursiveClever

Now we go back to my clever idea from Tuesday and Wednesday about flattening recursion. The code I ended up with:

public static IEnumerable<TSource> SelectRecursiveClever<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, IEnumerable<TSource>> recursiveSelector)
{
    Stack<TSource> stack = new Stack<TSource>();
    source.Reverse().ForEach(stack.Push);
    while (stack.Count > 0)
    {
        TSource current = stack.Pop();
        yield return current;
        recursiveSelector(current).Reverse().ForEach(stack.Push);
    }
}

Note: ForEach is an extension method I created that does what Array.ForEach does: calls an Action<T> delegate on each item. In this case, pushing every item in the sequence into the stack.

Now the caller-side behavior of this is exactly the same as the "simple" version above. The implementation tries to be "clever" though, by discarding the "naive" use of recursion by replacing the call stack with a local stack. I was quite proud of this implementation. As I said on Tuesday:

If you can flatten a recursive implementation, you will have a better understanding of what's really going on under the covers.

Gulp. Perhaps I spoke to soon.

The Problem with Clever

I showed a co-worker this code. It took a bit of work to explain the use of .Reverse(). Stacks are Last-in-first-out, so if you want to get the first item out first, you have to put it in last.

Explaining this hurt my head a bit. In the "simple"--read "naive"--implementation, one didn't have to reverse the enumeration. Why should the flattened version be different?

The answer: it shouldn't.

At some point in the "clever" implementation, every item is on the stack. This means if you have a very wide tree, the stack could grow to be huge.

Imagine your recursiveSelector is smart about not loading all items at a given level into memory at one time--the benefit of sequences, right? It doesn't matter, because SelectRecursiveClever will load everything in one level into a stack. It trades the potential benefit of a smaller call stack with the potential blow-up of your working set when iterate over a folder with 10,000 sub-folders.

Oops.

You have to keep track of your depth in the recursion somewhere: either the runtime stack or your own stack.

But all you have to keep track of is where you are in each sequence at each level. You don't have to queue up all of the items at a given level.

Turns out the CLR has this obscure feature to handle this: IEnumerator<T>.

Yeah, not so obscure.

It's actually what the simple version of this code does. When you call down into the nested SelectRecursiveSimle, an IEnumerator<T> will be waiting patiently at the the current spot for the call to return.

Getting Smart(er): SelectRecursive

The code is more ugly, but it also does a better job of illuminating what is happening in the truly recursive, "simple" version.

public static IEnumerable<TSource> SelectRecursive<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, IEnumerable<TSource>> recursiveSelector)
{
    Stack<IEnumerator<TSource>> stack = new Stack<IEnumerator<TSource>>();
    stack.Push(source.GetEnumerator());

    while (stack.Count > 0)
    {
        if (stack.Peek().MoveNext())
        {
            TSource current = stack.Peek().Current;
            yield return current;
            stack.Push(recursiveSelector(current).GetEnumerator());
        }
        else
        {
            stack.Pop();
        }
    }
}

2008-01-19: Turns out this code is wrong, too.

The stack now holds on to what it should: the IEnumerator<T> at each level. The while loop runs through IEnumerator<T>.MoveNext(), going deeper with every stack.Push() until there are no more items and then "returning" with stack.Pop().

Popping the stack

It's pretty easy to implement a recursive construct using Linq. The first "simple" implementation works great and it's really useful when partying over the file system or any other hierarchy.

I still claim that flattening recursive code is a good thing to do for reasons I mentioned on Tuesday.

Just make sure you do it correctly.

Put another way: pay attention to your masters.

If you can't be smart, be simple.

Don't ever be clever.

Clever will burn you.

 

Happy hacking.

 

kick it on DotNetKicks.com

PS: SVN has been updated again with the latest code. Hopefully the last time I'll touch RecursiveSelect for a while.

Remembering why I like single-vendor platforms

Now before I start a flame war, remember what I wrote in September:

I believe in open standards. The only way to protect and encourage open standards is to have many prevalent implementations of said standards.

Having said that, there are still a lot of reasons to love single-vendor, even closed, platforms.

One of those reasons: compatibility.

I had a simple goal: change my blog theme from fixed-width to fluid-width.

Code lines tend to take up a lot more space than 450px. Formatting C# for narrow columns is a pain.

I searched and hacked in vane for over an hour before I found a CSS solution.

The whole time there was a 16-year-old inside of me yelling: "Just use tables! They worked great in 1996!"

I'm going to spare you the gnarly details, but it involves negative margins. (Yes, negative margins. I almost fell off my Swiss ball.) Huge props to the folks at Dynamic Drive for their straight-forward-as-can-be-expected walk-through of fluid, two-column layouts in CSS.

After a bunch of tweaking, I got everything looking good in Firefox. I then jumped into Live Writer to start writing. I updated the cached theme for my blog. It looked really broken. Why?

Well, Live Writer uses Trident--the IE rendering engine.

After much hacking, I discovered that IE cares about the order of <div> elements in situations where Firefox doesn't. Also, Firefox respects // to mark comments in CSS. IE doesn't.

After another hour, I got things working in both.

No I haven't tested in IE6 or Safari. Please let me know if you have issues.

I'm guessing I'm one of the few who look at my blog in a browser--most probably use a blog reader.

Good idea.

Wednesday, January 16, 2008

Flattening recursive algorithms with Linq

I wake up this morning to find a comment from Stefan regarding my post yesterday about flattening recursion:

In the future version of C# we may receive a new language construct yield foreach which will eliminate this problem. Read this paper by Erik Meijer or this blog post by Wes Dyer if you are interested.

Ironically, I had read the paper and associated blog post last week.

And it got me thinking: could I abstract out my recursive traversal?

Even better: could I abstract it out in a way that was Linq-friendly?

The answer to both: oh yeah.

Check out the browser-friendly source here.

Now the code to find all of the selected directories becomes

SubDirectories
.SelectRecursive(directory => directory.SubDirectories)
.Where(directory => directory.IsSelected);

How's that for straight-forward?

Note 1: The savvy reader will notice that the third implementation is now like the original: the target node is not included in SelectedDirectories if it is selected. I like this more.

Note 2: Since I made SelectRecursive more general, I'm not quite as efficient about creating a bunch of enumerable instances. I still (likely) save a lot in call stack space and having a general implementation is pretty cool.

Note 3: You'll notice that SelectRecursive handles the case where there recursiveSelector returns null. This is different than how default extensions like SelectMany work. It made my usage in this scenario cleaner, but it's important to note. Or not. This bothered me for reasons I'll go into in another post. The code as checked-in now throws if null is returned. These subtle implementation details can cause headaches later.

As I mentioned yesterday, you can get the full source code from my SVN repository. The new methods extension methods have been added to Extensions.cs in J832.Common.

Happy recursive Linq-ing!

Tuesday, January 15, 2008

Flattening recursive algorithms is like taking the stairs...

...it's rarely necessary, but you'll be better for it.

Okay, a forced analogy.

2008-01-19: I've learned a lot since Tuesday. Please read!

I'm sure many remember their first algorithms class and their first introduction to recursion: the infamous Tower of Hanoi problem. I'd been coding for a while when I was presented with this puzzle and wondered (probably out loud), "Why don't we use a more concrete example, like the file system?"

I guess I've always been more of a software engineer than a computer scientist.

While the idea of recursion is useful in many situations, the costs are rarely discussed. As our friends at Wikipedia mention:

...in today's programming languages, the stack space available to a thread is often much less than the space available in the heap, and recursive algorithms tend to require more stack space than iterative algorithms.

Well said.

I was hacking on some work stuff that required recursion-- specifically flattening a hierarchy. I realized I'd done this before, in the bag-o-tricks. I also realized how expensive it was.

Call stack for recursive function call

Not only was I paying in call stack space for every nested call, but I was also allocating a lot of enumerators.

Code for the SelectedDirectories getter.

if (m_directories != null)
{
    foreach (SelectableDirectory sd in m_directories)
    {
        if (sd.IsSelected)
        {
            yield return sd;
        }
        foreach (SelectableDirectory sd2 in sd.SelectedDirectories)
        {
            yield return sd2;
        }
    }
}

So how does one improve this? Replace the call stack with your own stack.

Stack<SelectableDirectory> directoryStack = new Stack<SelectableDirectory>();
directoryStack.Push(this);
while (directoryStack.Count > 0)
{
    SelectableDirectory currentDir = directoryStack.Pop();
    if (currentDir.m_directories != null)
    {
        for (int i = (currentDir.m_directories.Count - 1); i >= 0; i--)
        {
            directoryStack.Push(currentDir.m_directories[i]);
        }
    }
    if (currentDir.IsSelected)
    {
        yield return currentDir;
    }
}

The savvy reader will notice that the second implementation is slightly different: the target node is included if it is selected. Just a detail.

So, what has improved? Only one enumerator is created. The call stack space for the recursion is also eliminated. The cost is the creation of the local Stack<> to keep track of the location in the hierarchy, which is likely much smaller than the space required for a call stack frame.

Since we want to keep the original order of items returned, we also have to Push each level of directories into the Stack in reverse order, so that the Stack returns them in the original order.

Now how does this match up with our masters?

It's certainly less readable. Since the code's not documented, it would probably take longer for even a savvy dev to figure out what's going on. This means it's less maintainable--certainly a negative.

On the plus size, the scalability of this algorithm is now limited by the size of the heap, which is much larger than the call stack. This only matters if one plans to parse very deep directory structures, though.

Another plus is likely performance, since fewer objects are instantiated and the cost of manipulating a local Stack<> is likely much cheaper than churning the call stack. I say 'likely' because I'm not really sure. I should absolutely measure the performance to be certain. Even then, the perf gain is likely trivial unless this code is called a lot. In that case, it might make sense to cache the result of the method.

In the end (and as always), context really matters. I think this is a good exercise to understand the costs and to challenge one's understanding of recursion. If you can flatten a recursive implementation, you will have a better understanding of what's really going on under the covers--something that is always useful.

Happy hacking!

Note: the updated code for Folder Picker has been committed to the bag-o-tricks directory in my SVN repository. You can take a look at the old implementation using Tortoise. Right-click on Data.cs in the shell. Pick 'Show log' out of the Tortoise menu. Then right-click on revision 58 and pick 'Update item to revision'.

Update to revision

Saturday, January 12, 2008

A REAL update to the Bag-o-Tricks

The last update to the bag-o-tricks was pretty lame, I'll admit.

As I discussed a bit ago, a lot of people code to "get it done yesterday". It's clear, looking through a bunch of the code, that I had this mentality about a lot of the samples. Moreover, it's clear that the masters of code quality, maintainability, and best-practices were often ignored.

Here's an attempt to put my money where my mouth is.

The Goods

Binaries and Source [zip, 4.3MB]. Developed with Visual C# Express 2008.

The Details

  • Set - New!
    • The XBap I posted last week is now part of the bag-o-tricks.
    • Did some clever project linking to allow building XBap without duplicating files.
  • Interactive 3D - New!
    • Added the 3D demos I discussed a while ago
    • A lot of clean-up to make the code more suitable for general use
  • AnimatingTilePanel
    • Ability to animate in newly added items
    • Made dampening make sense: bigger number = more dampening
    • Add Variation property to make item movement make more organic, if desired
    • Added validation to the public properties
    • Moved frame tick register/de-register to new CompositionTargetRenderingListener
    • Perf: Stopped ‘ticking’ when nothing is changing
    • Stopped using clock time between ticks to affect animation: complexity with little benefit
    • Made ItemHeight/Width attached properties that can be added to a host ItemsControl.
    • Demo: moved to DemoCollection -> now you can see how changes to the source collection are reflected
  • Graph
    • Removed a completely silly use a Dictionary. Clever perf optimization that made the code bloated, confusing, and probably slower.
    • Renamed CoefficientOfDampening -> Dampening
    • Rename FrameRate -> Attraction
    • Removed unneeded HideAnimationManager -> thank you anonymous methods.
    • Demo: A bunch of clean-up in the Node data files. Should never have used DispaterObject.
    • Demo: Moved to dispatcher timer for churning the graph nodes: a lot cleaner and more efficient than a separate Thread.
  • Zap
    • Removed shameful implementation of IPropertyChanged on top of a DependencyObject
    • Eliminated gratuitous subclassing of DependencyObject by ZapCommandItem
    • Removed FirstPreviousNextLastCommand (and associated enum) -> thank you ActionICommand
    • Fixed some pretty glaring bugs in not-so-edge cases
    • Demo: moved to DemoCollection
  • ActionICommand - New!
    • Commands often expose the functionality of existing methods. So why can’t exposing a command be as simple as wrapping the existing method? Exactly.
  • WrapperElement - New!
    • A while ago, I discussed not subclassing Panel unless you’re making a Panel. Well, sometimes all you want to do is compose a single element without exposing it's state to the world. WrapperElement makes the process of wrapping a child element trivial.
  • CompositionTargetRenderingListener - New!
    • A class that can be used to manage listening to the static CompositionTarget.Rendering event. I use this pattern so much, it made sense to make a separate class.
  • Demo: DemoCollection - New!
    • Writing controls that handle INotifyCollectionChange can be tough. Wouldn’t it be nice to have a class that makes testing (and then showing off) your list-bound control easy? I thought so.
  • General
    • Removed a lot of unused parameters and privates. Thanks, FxCop.
    • Demo: Moved the introduction page to FlowDocument. Why I didn’t do this a year ago, I’ll never know.

As always, the SVN location has been updated. Patches are always welcome (No one has taken me up on this yet. Would love to try it out.)

Enjoy and happy hacking!

Tuesday, January 8, 2008

WPF 3.5 Demo Posted: Add-ins and Interactive 3D

Way back in August, I posted about my last Channel 9 interview where I discussed new stuff in WPF for 3.5. At the time, I was a slacker about getting the code for the demos out.

WPF 3.5 Demo Code

Well Karsten has picked up my slack.

I only have C# 2008 Express installed and for some reason it doesn't like how complicated I made the solution, so I can't claim to have built/run the code as Karsten has posted it. I'm sure it's fine, though.

WPF Set - This is a good stopping spot

WPF Set - 2008-01-08

  • The graphics pretty much match the actual game now.
  • Moved the New Game button to minimize accidental clicking.
  • Some small tweaks to the game logic.

URLs are the same as before:

Bleh! The third night this darn game has kept me up past midnight. I need another hobby.

Sunday, January 6, 2008

The Game "Set" in WPF (Redux)

Yesterday (well, early this morning) I posted my first stab at the game Set implemented in WPF.

Amazing what 20 hours of bake time can do.

  • Removed insanely complex and unnecessary optimization that made the code for SetGame.TryPlay almost un-readable.
  • Cleaned up the 'test' mode