Showing posts with label pattern. Show all posts
Showing posts with label pattern. Show all posts

Wednesday, January 16, 2013

Final pool version

Since I went from C# to AS3 in order to complete web games I realized that the lack of generics in AS3 was going to be a huge problem for my pooling system, this forced me to think things once again and the result was something more elegant, secure and completely contained within the pooled class.

Making use of the factory design pattern once again I was able to create a pool system within the same class (which is now a template in my IDE), here is how it goes:

public class PooledItem
{
   private static var PoolHead:PooledItem;
   private var Next:PooledItem;
   private var Self:PooledItem;

   public function PooledItem()
   {
      Self = this;
   }

   public static function Create():PooledItem
   {
      var Vessel:PooledItem;
      if(PooledHead != null)
      {
         Vessel = PoolHead;
         PoolHead = PoolHead.Next;
      }
      else
      {
         Vessel = new PooledItem();
      }
      
      return Vessel;
   }
}


The PoolHead is private and static, making it unique locally and impossible to access from outside this class, then we have the Next and the Self which are unique to each instance of the PooledItem, and finally we have a factory pattern which creates a new instance of a PooledItem if the head is null, but if the head is not null it will return it and set the new head as the next element in the queue.

One thing to have in mind is that AS3 does not allow to have private constructors, thus making it possible to create an instance of the PooledItem without the factory method, if this happens and you don't properly get rid of it by calling its recycle method then you will have an extra element (outside the pool) doing nothing, but even if you create it without the "create" function you can still put it back in the pool by calling recycle, so no real harm done if handled properly, still if this was not AS3 I would make the constructor private.

Going to the recycle function now, the recycle function is where I do all my clean up code (if required depending on the elements of the class) as well as to put elements back into the pool:

public function Recycle():void
{
   //Do clean up code, maybe recycle other pooled items that were created within this
   //class or release references of an element to let GC deal with it, etc.

   Next = PoolHead; //we set the next element as the current head.
   PoolHead = Self; //and finally we set the this element as the new head.
}


And that's it, it is amazing how essential and memory friendly this can be, allocating memory and deallocating memory can be very tasking in the system, specially if you are planning on putting your games in mobile devices, have in mind also that the more memory you use the more battery it might consume, so in order to have some balance make sure to maintain your pools, this can be achieve by an internal reference counter and releasing some of them if the number gets to a certain point, however you want to handle that I will leave to you.


Saturday, August 18, 2012

Recursion

I have heard a lot about how recursion is bad, and why we should use collections instead and that collections are faster/safer, I believe it, but recursion has it's moments when it proves to be more useful than collections.

When you have that typical scenario of nodes, with one child and one parent (or many of both, etc) and then you call a function that calls the same function of either the parent of the child, that's a recursive function call, it will iterate all the elements that satisfy the criteria, such as "Draw all the children of this node", then we call draw on the parent, and the parent call draw on the children, etc.

What I think is bad about recursion is when the function being used recursively needs to pass arguments to be further tested down the line of nodes, or when the function itself returns a value to be processed by the parent, this is bad simply because we need to allocate memory for as long the functions we are using are alive (memory in the stack), for example if a parent node needs to count all it's children it could send an int by reference down the line and tell the children to add one or the children could return an int that's equal to the current number + 1, the stack wont release memory until the functions are finalized.

This could be avoid nevertheless, if you must have something to be analyzed down the line then you could make use of a "static" variable, that means you just need to set that variable once and all the nodes will know about it (a local static variable), that means you are not really allocating memory per call, just looking at memory already available to you.

I used recursion to add new elements to my drawing sorting, this proved to be quite fast and efficient, so instead of using a collection I used a node system that holds an "IDrawSorted" type of object and calls draw on it whenever the parent node needs to draw, code example:

public class SortingNode
    {
        public static SortingNode TopParent;
        static Poolean NodePool = new Poolean(1000, 100);
        public static SortingNode FindingAPlace;

        public SortingNode Child;
        public SortingNode Parent;
        public IDrawSorted Drawer;
        public int Z;

In the fields we have 2 static variables, one for the node that is being analyzed and another one for the current top parent, this node class is also pooled, take a look at my previous post to know about how the Poolean class works. After that you can see that the node can contain a child and a parent, as well as the information of the IDraw (The actual drawing object and it's Z position for Z sorting).

public static void Create(out SortingNode Vessel)
        {
            NodePool.Get(out Vessel);
        }

As a rule I never ever use "new" in my code design, simply because using new on objects can cause memory leaks, so all my objects are properly managed, using factory pattern methods to get "instantiated" since they really are not being created on the fly, they already live in a pool.

public void Add()
        {
            if (FindingAPlace.Z <= Z)
            {
                if (Child != null)
                {
                    Child.Add();
                }
                else
                {
                    Child = FindingAPlace;
                    FindingAPlace.Parent = this;
                }
            }
            else
            {
                if (Parent == null)
                {
                   //if a node has no parent, it is the head.
                    TopParent = FindingAPlace;
                    FindingAPlace.Child = this;
                    Parent = FindingAPlace;
                }
                else
                {
                    Parent.Child = FindingAPlace;
                    FindingAPlace.Child = this;
                    FindingAPlace.Parent = Parent;
                    Parent = FindingAPlace;
                }
            }
            FindingAPlace = null;
        }
So, this is a recursion function, as you can see it does not take any arguments and it returns nothing, so prior to call this function the information you want to analyze has to be pre loaded to the static variable inside the class, this is accomplished by accessing them by "SortingNode.FindingAPlace = YourDrawer;", this way we only set it once, and then send it to analyze. In this function we are looking if the current Z value we are passing through the static IDrawSorted is smaller or equal to the current's IDrawSorted living in the node, we will check if it has a child in the event that it is smaller or equal, so we further test down the line until we find a place were to place this new node, this is faster than a normal collection simply because I do not need to change or push down all the resting elements down the line by one because if we need to insert something in between the line we simply just change the references pointing to the parents and children to of the new node.
public void Draw()
        {
            if (Child != null)
            {
                Child.Draw();
            }
            Drawer.Draw();
        }
Recursively calling draw on every children, this is a secondary function.
public void StartDrawing()
        {
            if (Parent != null)
            {
                Parent.StartDrawing();
            }
            else
            {
                Draw();
            }
        }
this is the the entry point to the drawing class, I do it this way in case that the node that called "StartDrawing" might not be the current top node, therefore we need to find the top node to start calling draw.
public void Recycle()
        {
            if (Child != null)
            {
                Child.Parent = null;
                Child.Recycle();
            }
            Child = null;
            NodePool.ReturnPoolable(this);
        }

    }


Finally we have a recycle method to put the entire collection back into the pool when we don't need it anymore.




And that concludes my recursion method and how I use them to sort my drawing, this is working nicely in the Xbox. Currently I am working on an Xbox title because I am waiting for the new Windows phone 8 to come out as well as the new Visual Studio, once that's out I will be porting all my code to C++.

Friday, August 17, 2012

New Poolean

Looking back to when I made my first "Pool" (called Poolean) and the reasons why I made it the way it was I came to realize I was trying to avoid using "List.Remove(T)" besides avoiding to create new elements every time something was needed.
Some time after that I stumbled upon a performance problem that was going to 
hinder my game if the number of elements to be managed was going to be big, let'ssay that a pool is used a lot, meaning that the elements within the pool are
almost always "In use" and often the pool requires to expand (create new elementsto accommodate demand). Following the way the pool used to work, I would have to check if the "next" element was free, and if it was not continue until I ran out of space, then I started back from 0 to right before the element I just used, andif nothing was available then expand the pool.
The problem with this is that if I want something that requires big numbers (likeparticles) it would get hairy real quick.
I was trying to make a class that could hold a collection of objects and be able to remove the objects without having to shift things around (like List.Remove(T) does) because once again that would be very slow, I came with the idea of removing the certain element and swapping the last element in the collection to the position of the element we just removed, putting the count down by one and that would be all, in order to do this, the object I wanted to use in this "Collection" would have to contain an interface that allows access to certain index number, just a simple property to know in which position the element is in the collection. This methodology could fix my Poolean issue, by knowing how many items are in the pool, and knowing I always remove the last one, this made the entire "Searching for the next element" completely obsolete, which made me happy, so now the new Poolean looks like this:    


public class Poolean<T> where T: new()
    {
        public T[] Pool;
        public int Size;
        public int GrowthAmount;
        public int CurrentFreeIndex;
        public Type TypeOfT;

        public Poolean(int size, int Growth)
        {
            CurrentFreeIndex = size - 1;
            GrowthAmount = Growth;
            TypeOfT = typeof(T);

            Pool = new T[size];

            Size = size;

            for (int i = 0; i < Size; i++)
            {
                T NewElement = (T)Activator.CreateInstance(TypeOfT);
                Pool[i] = NewElement;
            }
        }

        public void Get(out T Vessel)
        {
            if (CurrentFreeIndex > -1)
            {
                Vessel = (T)Pool[CurrentFreeIndex];
                Pool[CurrentFreeIndex] = default(T);
                CurrentFreeIndex--;
            }
            else
            {
                //Expand
                CurrentFreeIndex += GrowthAmount;
                Size += GrowthAmount;
                Pool = new T[Size];
                for (int i = 0; i < GrowthAmount; i++)
                {
                    T NewItem = (T)Activator.CreateInstance(TypeOfT);
                    Pool[i] = NewItem;
                }

                //try again
                Vessel = (T)Pool[CurrentFreeIndex];
                Pool[CurrentFreeIndex] = default(T);
                CurrentFreeIndex--;
            }
        }

        public void ReturnPoolable(T Poolable)
        {
            CurrentFreeIndex++;
            Pool[CurrentFreeIndex] = Poolable;
        }
    }


As you can see it is a lot shorted and easier to understand, let's go over the Constructor first, in the constructor you specify how many elements do you want in the pool to begin with and in the event that the pool runs out of space, how many elements you want to add, pretty simple, there we define what type T is and then we populate the array of Ts with objects of type T. Then we have the "Get" function which takes an element out of the pool if it has any left and if it doesn't it expands, and finally we have the "ReturnPoolable" which adds the element back to the pool and gets the count up by one.

This made the pool lightning faster, but I hope I come up with an idea to make it even faster.