I wrote a small class that demonstrates my problem:
class Root
{
private Leaf RootLeaf;
private Dictionary<object, Leaf> AllItems = new Dictionary<object, Leaf>(); //dictionary contains a reference to each item, and the leaf it is assigned to (its parent)
public Root()
{
RootLeaf = new Leaf();
}
public List<object> GetAllChildren
{
get { return RootLeaf.getAllChildren; }
}
public void Add(object o)
{
Leaf AddedTo = RootLeaf.Add(o);
AllItems.Add(o, AddedTo); //Add object reference to AllItems dictionary
}
private IEnumerable<object> GetNeighbors(object obj)
{
foreach (object o in this.AllItems[obj].getAllChildren)
{
if (obj != o)
yield return o;
}
}
public void Update()
{
foreach (KeyValuePair<object, Leaf> i in AllItems)
{
foreach (object b in this.GetNeighbors(i.Key))
{
//Would do collision checks here
}
}
}
}
class Leaf
{
private const int MaxChildCount = 1;
private List<object> Children = new List<object>();
private Leaf[] ChildLeaves = null;
private bool _LeavesGenerated = false; //Have the leaves been created? (Low Level, do not touch)
private bool HasLeaves = false; //Should we use the leaves?
protected void CreateLeaves()
{
if (!_LeavesGenerated)
{
//create each of the four leaves
for (int i = 0; i < 4; i++)
ChildLeaves[i] = new Leaf();
_LeavesGenerated = true;
}
HasLeaves = true;
}
protected void RemoveLeaves()
{
HasLeaves = false;
}
/// <summary>
/// Returns children of this leaf, and all of its subleaves
/// </summary>
public List<object> getAllChildren
{
get
{
List<object> outp = Children.ToList();
if (HasLeaves)
{
foreach (Leaf l in ChildLeaves)
outp.AddRange(l.getAllChildren);
}
return outp;
}
}
/// <summary>
/// Get count of all children in this leaf, and its subleaves
/// </summary>
public int getChildCount
{
get
{
int outp = Children.Count;
if (HasLeaves)
{
foreach (Leaf l in ChildLeaves)
outp += l.getChildCount;
}
return outp;
}
}
static Random rand = new Random();
/// <summary>
///
/// </summary>
/// <param name="o">The object to be added</param>
/// <returns>The leaf the object was added to</returns>
public Leaf Add(object o)
{
if (Children.Count >= MaxChildCount)
{
//Pick random subleaf, I know this isn't correct for a quadtree, but it will simplify this explanation code
if (!HasLeaves)
CreateLeaves();
return ChildLeaves[rand.Next(0, 3)].Add(o);
}
else
{
Children.Add(o);
return this;
}
}
}
I ran this through the ANTS profiler, and it not surprisingly pulled the Leaf.getAllChildren
and Leaf.getChildCount
as the two most expensive operations. I'm ok with how everything thing else is laid out. My question is: how could I optimize the two aforementioned properties?
The properties are called when the Root.Update()
function is run.
Main()
method which creates these objects and calls their methods. \$\endgroup\$