Showing posts with label kata. Show all posts
Showing posts with label kata. Show all posts

Friday, 21 January 2011

A simple paged IList, arrays of doubles and the LOH

Turns out large (1000+ elements) arrays of doubles get put on the Large Object Heap, rather than living out their days on the normal heap. Apparently, it’s an optimization by Microsoft to keep the arrays aligned to 8-byte boundaries (as the LOH is collected but not compacted).

This leads to some exciting behaviour if you’re using a List<double> that reaches 1000 doubles. Especially if you’re not thinking about it, and just allowing it to expand, as you’ll keep recreating new arrays whenever you reach the array size limit. Did MS choose 1000 or 1024? Not sure.

A colleague hit this recently in our production code. In our specific case the right thing to do was stop using so many large arrays of doubles, as they weren’t needed.

Alternatively, one way to avoid fragmentation and LOH usage would be to preallocate large arrays or Lists of doubles – if you know how large an array you’re going to need.

Another way would be to create a paged IList implementation, one keeps its contents in a set of arrays that are sized just under the maximum to avoid LOH use.

Yes, it subverts Microsoft’s performance enhancement, and yes, I’m sure they know what they’re doing. I’m not sure what they’re doing though, so if nothing else it means I can run some comparisons, iterating through a list of doubles, for example.

Conveniently it also makes another nice workout – some code below, using a List<T[]> as the underlying page collection. I've not implemented Remove, RemoveAt and Insert methods as I didn't immediately need them for the tests I had in mind.

public class PagedList<T> : IList<T>
{
 private int _pageSize = 100;

 private int _currentPage = 0;

 private int _currentPageHighwatermark = 0;

 private List<T[]> _underlyingList;

 public PagedList(int pageSize)
 {
  _pageSize = pageSize;
  _underlyingList = new List();
  _underlyingList.Add(new T[_pageSize]);      
                    // if it has pages already, we'll be tagging an 
                    // extra empty page on the end ...
  _currentPage = _underlyingList.Count - 1;                   
                    // also, if it has pages already then the 
                    // highwatermark will be wrong            
 }

 /// <returns>Index of element, -1 if not found</returns>
 public int IndexOf(T item) // consider boxing, unboxing
 {
  int index = 0;
  var iter = _underlyingList.GetEnumerator();
  while(iter.MoveNext())
  {
   foreach(var t in iter.Current)
   {
    if(t.Equals(item))
    {
     return index;
    }
    index++;
   }
  }
  return -1;
 }

 public void Insert(int index, T item)
 {
  throw new NotImplementedException();
 }

 public void RemoveAt(int index)
 {
  throw new NotImplementedException();
 }

 public T this[int index]
 {
  get
  {
   int desiredPage = Math.Abs(index/_pageSize);
   int desiredPageIndex = index%_pageSize;
   if (desiredPage * _pageSize + desiredPageIndex > 
                                _currentPage * _pageSize + _currentPageHighwatermark 
                                || index < 0)
   {
    throw new IndexOutOfRangeException("Index was out of bounds");
   }
   return _underlyingList[desiredPage][desiredPageIndex]; // Consider what to do about nulls here
  }
  set
  {
   // Check whether index is out of range
   int desiredPage = Math.Abs(index / _pageSize);
   int desiredPageIndex = index % _pageSize;
   if (desiredPage * _pageSize + desiredPageIndex > 
                                _currentPage * _pageSize + _currentPageHighwatermark 
                                || index < 0)   {
    throw new IndexOutOfRangeException("Index was out of bounds");
   }
   _underlyingList[desiredPage][desiredPageIndex] = value;
  }
 }

 public void Add(T item)
 {
  var page = _underlyingList.Last();
  if (_currentPageHighwatermark == _pageSize)
  {
   _underlyingList.Add(new T[_pageSize]);
   _currentPage++;
   _currentPageHighwatermark = 0;
  }
  _underlyingList[_currentPage][_currentPageHighwatermark] = item;
  _currentPageHighwatermark++;
 }

 public void Clear()
 {
  _underlyingList.Clear();
  _underlyingList.Add(new T[_pageSize]);
  _currentPage = 0;
  _currentPageHighwatermark = 0;
 }

 public bool Contains(T item)
 {
  var iter = _underlyingList.GetEnumerator();
  while (iter.MoveNext())
  {
   foreach (var t in iter.Current)
   {
    if (t.Equals(item))
    {
     return true;
    }
   }
  }
  return false;
 }

        public void CopyTo(T[] array, int arrayIndex)
        {
            // Do out-of-bounds checking on arrayIndex, sizeof array
            for(int i = arrayIndex; i < Count; i++)
            {
                array[i - arrayIndex] = this[i];
            }
        }

 public int Count
 {
  get { return (_currentPage*_pageSize) + _currentPageHighwatermark; }
 }

 public bool IsReadOnly
 {
  get { throw new NotImplementedException(); }
 }

 public bool Remove(T item)
 {
  throw new NotImplementedException();
 }

 public IEnumerator<T> GetEnumerator()
 {
  return new PagedListEnumerator<T>(this);
 }

 private class PagedListEnumerator<T> : IEnumerator<T>
 {
  private PagedList<T> _underlyingPagedList;
  private int _cursor;

  public PagedListEnumerator(PagedList<T> list)
  {
   _underlyingPagedList = list;
   _cursor = -1;
  }

  public void Dispose()
  {
  }

  public bool MoveNext()
  {
   if (_cursor < _underlyingPagedList.Count)
    _cursor++;

   return (!(_cursor == _underlyingPagedList.Count));
  }

  public void Reset()
  {
   _cursor = -1;
  }

  public T Current
  {
   get { return _underlyingPagedList[_cursor]; }   // Handle fail when out of bounds
  }

  object IEnumerator.Current
  {
   get { return Current; }
  }
 }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
}

Monday, 29 November 2010

Conway’s Game of Life (as an Android live wallpaper)

Having found Conway’s Game of Life to be a useful kata in C#, I thought I’d use it to explore some other technology. I’ve had an HTC Desire Android smartphone for a little while, so thought I’d see how hard it was to port something over.

I was hit by a number of gotchas while writing it – mostly down to using the API for the first time, and by not using Eclipse, instead using notepad++ and jdb to code and debug. jdb gave me a little trouble, but soon figured it out (on stackoverflow and here), realising that I had to make a socket connection to the emulator, and not the shared memory connection I seemed to be defaulting to.

I worked up a very simple app by just porting the core Life code I create in kata to Java, and then writing a minimal presenter over the top. The presenter comprises an Activity and an View; the Activity was just responsible for spinning up the backend engine – the View. The View is responsible both for keeping the evolution of the cells going, and displaying the current state. Dirty, but it worked.

Spot the glider ...In this case, and like many of the examples, there’s a message handler pump that keeps the model going. Messages to the renderer are posted delayed by the desired frame rate.

Converting the app to a live wallpaper sees the Activity transformed into a WallpaperService, which means we need to override the method onCreateEngine – in the case of a live wallpaper a specific Engine class actually drives the underlying model, and presents you with a SurfaceHolder on which to render the wallpaper.

As a  result, LifeEngine was reworked to inherit from Engine and render using a SurfaceHolder rather than a Canvas. The only real wrinkle there is that the Surface doesn’t get wiped between renders, so you need to wipe it yourself.

I wanted to pop up a dialog or other window when the user tapped the screen – that turned out to be not as straightforward as I’d assumed from a wallpaper. Handling the tap is easy enough, but bringing up a dialog less so.

Currently you can download the wallpaper here on the market, and the project should be up soon.

Tuesday, 23 November 2010

Conway's Game of Life

Conway’s Game of Life must be one of the most continuously re-implemented algorithms in the history of software development. In case you’ve not seen it, the Game of Life is played out with cellular automata, or cells that are switched on or off by a set of rules. The rule set is applied to the all cells in one step, creating a new state or generation repeatedly.

A cellular automata implementation shares much with other problems often solved with stepwise and parallelizable modelling – as say some approaches to quantum electrodynamics, fluid mechanics and other physical models – so I figured it was as good a motif as any to explore some new technologies, and maybe work up some kata along the way.

The first step was to build up a core library code that implements the Game of Life. For a first implementation we need a grid of cells on which to play out the game, and a rule set that transforms the grid from one state to another.

This immediately sounded like a good basis for relatively quick kata. There are a couple of useful principles involved: practically, it’s immediately amenable to unit testing as we explicitly define the state we expect from any transformation; and the outline of the algorithm – applying a rule set to a whole state to transform it into a new state – is a useful one to remember.

So, to outline the kata, we need:

  1. A 2d grid that reports whether a cell at x,y is on (alive); allows us to set on/off state at x,y; allows us to clear (all off) and reset (random on/off); and perhaps display a simple representation of the grid to stdout.
  2. A rule set that transforms a 2d grid and returns a new 2d grid with some rule set applied.
  3. Unit tests should express the rules in terms of expected start and end grid states.

The rules – well they’re written up in many places, but to summarise:

  1. Cells with fewer than 2 neighbours die.
  2. Cells with 2 neighbours that are alive, stay alive.
  3. Cells with 3 neighbours stay alive if alive, or come to life if dead.
  4. Cells with 4 or more neighbours die.

The last time I went through this kata my set of C# NUnit tests looked like this – but I’d say the idea is to start from scratch each time:

    [TestFixture]
    public class CoreTests
    {
        [Test]
        [ExpectedException("System.ArgumentOutOfRangeException")]
        public void StubGridDoesntTakeNegativeWidth()
        {
            var g = new StubLifeGrid(-1, 1);
        }

        [Test]
        [ExpectedException("System.ArgumentOutOfRangeException")]
        public void StubGridDoesntTakeNegativeHeight()
        {
            var g = new StubLifeGrid(1, -1);
        }

        [Test]
        [ExpectedException("System.ArgumentOutOfRangeException")]
        public void StubGridOutOfRangeWidthRequestFails()
        {
            var g = new StubLifeGrid(2, 2);
            g.AliveAt(3, 1);
        }

        [Test]
        [ExpectedException("System.ArgumentOutOfRangeException")]
        public void StubGridOutOfRangeHeightRequestFails()
        {
            var g = new StubLifeGrid(2, 2);
            g.AliveAt(1, 3);
        }

        [Test]
        [ExpectedException("System.ArgumentOutOfRangeException")]
        public void StubGridSetOutOfRangeWidthFails()
        {
            var g = new StubLifeGrid(2, 2);
            g.Set(3, 1, true);
        }

        [Test]
        [ExpectedException("System.ArgumentOutOfRangeException")]
        public void StubGridSetOutOfRangeHeightFails()
        {
            var g = new StubLifeGrid(2, 2);
            g.Set(1, 3, true);
        }

        [Test]
        public void DiesWithNoNeighbours()
        {
            ILifeGrid g = new StubLifeGrid(3, 3);
            // Starts alive
            g.Set(1, 1, true);
            
            var r = new BasicRuleSet();
            g = r.Transform(g);

            Assert.IsFalse(g.AliveAt(1, 1));

            // Starts dead
            g = new StubLifeGrid(3, 3);
            g.Set(1, 1, false);

            g = r.Transform(g);

            Assert.IsFalse(g.AliveAt(1, 1));
        }

        [Test]
        public void DiesWithOneNeighbour()
        {
            ILifeGrid g = new StubLifeGrid(3, 3);
            // Starts alive
            g.Set(1, 1, true);
            g.Set(0, 0, true); // create all possible and test

            var r = new BasicRuleSet(); // static, in fact?
            g = r.Transform(g);

            Assert.IsFalse(g.AliveAt(1, 1));

            // Starts dead
            g = new StubLifeGrid(3, 3);
            g.Set(1, 1, false);
            g.Set(0, 0, true);

            g = r.Transform(g);

            Assert.IsFalse(g.AliveAt(1, 1));
        }

        [Test]
        public void StaysAliveWithTwoNeighbours()
        {
            ILifeGrid g = new StubLifeGrid(3, 3);
            g.Set(1, 1, true);
            g.Set(0, 0, true);
            g.Set(0, 1, true);
            g.Display();

            var r = new BasicRuleSet(); // static, in fact?
            g = r.Transform(g);
            g.Display();

            Assert.IsTrue(g.AliveAt(1, 1));

            // starts dead, stays dead
            g = new StubLifeGrid(3, 3);
            g.Set(1, 1, false);
            g.Set(0, 0, true);
            g.Set(0, 1, true);
            g.Display();

            r = new BasicRuleSet(); // static, in fact?
            g = r.Transform(g);
            g.Display();

            Assert.IsFalse(g.AliveAt(1, 1));
        }

        [Test]
        public void BornWithThreeNeighbours()
        {
            ILifeGrid g = new StubLifeGrid(3, 3);
            g.Set(1, 1, false);
            g.Set(0, 0, true);
            g.Set(0, 1, true);
            g.Set(0, 2, true);
            g.Display();

            var r = new BasicRuleSet(); // static, in fact?
            g = r.Transform(g);
            g.Display();

            Assert.IsTrue(g.AliveAt(1, 1));
        }

        [Test]
        public void StaysAliveWithThreeNeighbours()
        {
            ILifeGrid g = new StubLifeGrid(3, 3);
            g.Set(1, 1, true);
            g.Set(0, 0, true);
            g.Set(0, 1, true);
            g.Set(0, 2, true);

            var r = new BasicRuleSet(); // static, in fact?
            g = r.Transform(g);

            Assert.IsTrue(g.AliveAt(1, 1));
        }
    }