Developing web applications, there are scenarios and patterns which repeat over and over, day after day, when working with the underlying data. One of these scenarios which I see very often is when there are two or more collections with one-to-many or many-to-many relationships which require filtering or joining on some type of key to ultimately perform a computation that requires the parent and the child in a hierarchy. Let’s explore two ways of solving this problem, first using nested loops with sub-queries, and then using LINQ join queries, and figure out which of the two solutions has the best performance and performs the least amount of iterations.

First, let’s define our Parent class:

public class Parent
{
    public Guid Id { get; set; }
 
    public string Name { get; set; }
}

Next, let’s define our Child class, which will contain a ParentId property to reference its Parent:

public class Child
{
    public Guid Id { get; set; }
 
    public string Name { get; set; }
 
    public Guid ParentId { get; set; }
}

Next, in order to gather profiling data, we’re going to create a custom implementation of the IEnumerable and IEnumerator interfaces, named LoggingEnumerable and LoggingEnumerator, which will log each call to the IEnumerator members.

The LoggingEnumerable class implements GetEnumerator by returning a new instance of the LoggingEnumerator class, which will do the actual logging.

public class LoggingEnumerable<T> : IEnumerable<T>
{
    private readonly IEnumerable<T> _enumerable;
    private readonly Action<string> _log;
 
    public LoggingEnumerable(IEnumerable<T> enumerable, Action<string> log)
    {
        _enumerable = enumerable;
        _log = log;
    }
 
    public IEnumerator<T> GetEnumerator()
    {
        return new LoggingEnumerator<T>(_enumerable.GetEnumerator(), _log);
    }
 
    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

The LoggingEnumerator implements the IEnumerator interface by proxying calls to the inner IEnumerator instance, but logs access to the members using the provided logging function.

public class LoggingEnumerator<T> : IEnumerator<T>
{
    private readonly IEnumerator<T> _enumerator;
    private readonly Action<string> _log;
 
    public LoggingEnumerator(IEnumerator<T> enumerator, Action<string> log)
    {
        _enumerator = enumerator;
        _log = log;
    }
 
    public void Dispose()
    {
        _log("Dispose");
        _enumerator.Dispose();
    }
 
    public bool MoveNext()
    {
        _log("MoveNext");
        return _enumerator.MoveNext();
    }
 
    public void Reset()
    {
        _log("Reset");
        _enumerator.Reset();
    }
 
    public T Current
    {
        get
        {
            _log("get_Current");
            return _enumerator.Current;
        }
    }
 
    object IEnumerator.Current
    {
        get { return Current; }
    }
}

Having defined our profiling classes, now let’s define our logging functions; we’ll want to log the Parent iterations and the Child iterations separately, so let’s setup two functions that we can pass to the LoggingEnumerable constructor:

 
private readonly Dictionary<string, int> _childrenLog = new Dictionary<string, int>();
private void ChildrenLog(string key)
{
    if (!_childrenLog.ContainsKey(key))
        _childrenLog[key] = 0;
    _childrenLog[key]++;
}
private readonly Dictionary<string, int> _parentLog = new Dictionary<string, int>();
private void ParentsLog(string key)
{
    if (!_parentLog.ContainsKey(key))
        _parentLog[key] = 0;
    _parentLog[key]++;
}

Next, to simulate some work we’ll write a function that we can execute during our iterations; this simple function will compute the hash code of parent and child.

 
private int ComputeHash(object parent, object child)
{
    return parent.GetHashCode() & child.GetHashCode();
}

Now we’re ready to write our profiling code, using a data source _parents and _children collection with 100 parents and 10000 children.

Using nested loops with LINQ subqueries the resulting profiling code would be:

 
public void Profile_Enumerations_Using_Nested_Loops()
{
    var parents = new LoggingEnumerable<Parent>(_parents, ParentsLog);
    var children = new LoggingEnumerable<Child>(_children, ChildrenLog);
 
    var codes = new List<int>();
    foreach (Parent parent in parents)
    {
        Guid parentId = parent.Id;
        IEnumerable<Child> ptc = children.Where(x => x.ParentId == parentId);
        foreach (Child child in ptc)
        {
            int hash = ComputeHash(child, parent);
            codes.Add(hash);
        }
    }
 
    Console.WriteLine("{0} computations completed.", codes.Count);
    foreach (var kvp in _childrenLog)
    {
        Console.WriteLine("Children_{0}:{1}", kvp.Key, kvp.Value);
    }
    foreach (var kvp in _parentLog)
    {
        Console.WriteLine("Parent_{0}:{1}", kvp.Key, kvp.Value);
    }
}

Using LINQ join queries the resulting profiling code would be:

 
public void Profile_Enumerations_Using_Linq_Join()
{
    var parents = new LoggingEnumerable<Parent>(_parents, ParentsLog);
    var children = new LoggingEnumerable<Child>(_children, ChildrenLog);
 
    IEnumerable<int> ptc = from p in parents
        join c in children
            on p.Id equals c.ParentId
        select ComputeHash(p, c);
 
    List<int> codes = ptc.ToList();
 
    Console.WriteLine("{0} computations completed.", codes.Count);
    foreach (var kvp in _childrenLog)
    {
        Console.WriteLine("Children_{0}:{1}", kvp.Key, kvp.Value);
    }
    foreach (var kvp in _parentLog)
    {
        Console.WriteLine("Parent_{0}:{1}", kvp.Key, kvp.Value);
    }
}

Finally, running the profiling methods as tests yields the following data:

 
Output from LinqCycles.LinqCyclesFixture.Profile_Enumerations_Using_Nested_Loops:
  10000 computations completed.
  Children_MoveNext:1000100
  Children_get_Current:1000000
  Children_Dispose:100
  Parent_MoveNext:101
  Parent_get_Current:100
  Parent_Dispose:1
 
Output from LinqCycles.LinqCyclesFixture.Profile_Enumerations_Using_Linq_Join:
  10000 computations completed.
  Children_MoveNext:10001
  Children_get_Current:10000
  Children_Dispose:1
  Parent_MoveNext:101
  Parent_get_Current:100
  Parent_Dispose:1

From which can validate that using LINQ join queries is far more efficient, and that the program iterates over the entire children collection only once, while using nested loops with sub-queries the sub-queries iterate over the entire children collection on for each parent! See the included sample solution and play around with the tests; things get much more interesting when adding additional layers to the hierarchy (e.g. adding grandparents).

Clone the sample solution here

On Friday afternoon May 09, 2014 the Mercury New Media team set off for Canoe Escape for our annual team event.  Upon arrival each team member was handed their oar, life jacket and demonstrated the finer points of paddling.  After our short tutorial we paired up with our paddling partner and headed for the river to begin our 4 mile adventure.   

Everyone had a job to do to make their ride down the river a success.  The bow rider was in charge of navigating and using the draw stroke to help steer.  The stern rider was responsible for steering and utilized the J-stroke as a rudder.  Each boat needed to work as a team to navigate down the Hillsborough River. 

The river snaked along with tight turns and narrow channels.  There was an abundance of wildlife; birds flying overhead and turtles sunning themselves on river logs. Gators slinked into the water from the shoreline and peeked their snouts above the surface. 

Half way down the river our group encountered a tree that had fallen the night before that blocked our path.  In true MNM fashion our teams had to Craft a solution to a Wicked Problem in order to move forward on our adventure.  Each team evaluated their position and decided as a team how to proceed.  Several got low in the boat and limbo styled through the blockade.  Others powered through the foliage and forged a new path.

After our 3 hour paddling trip we reached Morris Bridge Park and pulled our canoes on shore.  It was a great afternoon of fun, sun and team work!

 

A canoe on the water
Canoe Escape
a man paddling a canoe
a group of people in different canoes
Canoe Escape

In recent years, one of the biggest and most timely movements in web development has been the push towards responsive web design (a.k.a. RWD). And with good reason. For those who are unfamiliar with this concept, it allows your website to be viewed on an almost infinite number of devices and screen sizes, all while allowing you to control the message, design, and user experience that you want to deliver to your customers. For many, this might not seem like an important consideration, but when you dig deeper into how customers view your website, you’ll quickly realize the device fragmentation and wide range of screen sizes that your content can be viewed on.

Let’s quickly go back in time a few years (5-10), before smartphones and tablets were the norm. When designing websites, we only had to account for a handful of common desktop screen sizes to make sure they looked and worked correctly. Those days are long gone. With brand new phones and tablets being released almost daily, planning and designing for a handful of screen sizes and expecting everything to work is no longer acceptable. This is a hard lesson that some businesses are paying the price for currently. If your website is a traditional, non-responsive type, a user might not be able quickly get the info they need from your website, or worse, the site doesn’t display correctly on that particular device. If this is the case, what will prevent the customer from using your competitor’s website instead? Especially if your competition has optimized their site for mobile usage. The moment a user hits your website, the clock starts ticking. If you can’t help them quickly enough, they will look elsewhere for answers.

Today, web users move seamlessly from device to device (desktop at work, phone on commute home, tablet or laptop at home), so they expect usable, optimized delivery of the content across all of these devices. The challenge lies in the fact that all of these devices have varying screen resolutions and can all be used in different situations that affect how the information is consumed (for example, a customer using his iPhone on a crowded, noisy train). This is where the beauty of responsive web design comes into play because you can tailor your website to deliver content that is targeted to both the device being used as well as the viewing situation.

We’ve all found ourselves in a situation where we pull out our mobile device to quickly verify a business’s address or get their phone number. A common use of RWD is when a restaurant or business offers an optimized experience for smartphones. It’s safe to assume the user is currently on the move and needs quick, concise answers to common questions (directions, menu, hours of operation, phone number, etc.). Using RWD, we can tailor the smartphone experience to show the most important information front and center, in an easy to read fashion. So, instead of requiring a user to dig through a traditional website looking for the relevant information, we’ve designed the mobile experience to help them focus on solving their current problem quickly and easily. Once again, if we can’t answer these questions quickly, the consumer will move on to find them elsewhere.

Along with giving businesses the power to control the delivery of content to their customers, there are also plenty of other benefits that come along with RWD. One of the biggest is the fact that major search engines (especially Google) like the use of responsive design because there is no need for a dedicated “mobile” version of your website. Before RWD gained popularity, the concept of having a “mobile only” website alongside the desktop version was common. The biggest problem with this method was the fact that these were completely separate websites that required an entirely different design, separate maintenance, and separate Search Engine optimization and marketing efforts. In effect, businesses were maintaining 2 independent websites. Which is always a nightmare. RWD removes this need because you build one site that works for all devices. Another benefit is how your customers view your brand. With mobile use steadily increasing, users are getting more mobile savvy with each passing day and if they feel that your business isn’t keeping up with the times, they will move on to someone who they feel is more relevant. This concept runs even deeper because sometimes, even subconsciously, users might feel that if your website isn’t “current”, there might be deeper issues to consider, like security of their personal, credit card, or banking information.

In closing, as with many other technologies, there is always a question of how long a “standard” will remain and what will take its place. Responsive design is not a trend that will soon evaporate when the “next big thing” arrives. If anything, the need for RWD will only continue to increase with the constant addition of more devices and screen sizes. Because of this increasing need, the sooner a brand can “respond” to these requirements, the better.