Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

well, I am creating a voxel engine in C# and XNA and many posts I have posted on this site have been due to performace issues, many people suggested using a profiler to help me out. I have, and strangley enough the most functions that are costing me the most peformace according to the profiler, are the simplest. Here is the output of the profiler:

enter image description here

and here is the world code:

    public bool InBounds(int x, int y, int z)
    {
        if ((x < 0 || y < 0 || z < 0) ||
            x >= size.X || y >= size.Y || z >= size.Z)
        {
            return false;
        }

        return true;
    }

    public bool Exists(int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            Vector3i regionalPosition = GetRegionalPosition(x, y, z);
            Vector3i region = GetRegionPosition(x, y, z);

            return !(regions[region.X, region.Y, region.Z].Blocks[regionalPosition.X, regionalPosition.Y, regionalPosition.Z].BlockType == BlockType.none);
        }

        return false;
    }


    public void SetLight(int x, int y, int z, int light)
    {
        if (InBounds(x, y, z))
        {
            Vector3i regionalPosition = GetRegionalPosition(x, y, z);
            Vector3i region = GetRegionPosition(x, y, z);

            regions[region.X, region.Y, region.Z].QueueForBuild(BufferType.All);

            regions[region.X, region.Y, region.Z].Blocks[regionalPosition.X, regionalPosition.Y, regionalPosition.Z].Light = (byte)light;
        }
    }

    public int GetLight(int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            // ARRAYS start from ZERO
            // LOGIC starts from ONE

            Vector3i regionalPosition = GetRegionalPosition(x, y, z);
            Vector3i region = GetRegionPosition(x, y, z);

            return regions[region.X, region.Y, region.Z].Blocks[regionalPosition.X, regionalPosition.Y, regionalPosition.Z].Light;
        }

        return -1;
    }

    public Block GetBlock(Vector3 position)
    {
        int x = (int)Math.Floor(position.X);
        int y = (int)Math.Floor(position.Y);
        int z = (int)Math.Ceiling(position.Z);

        Block block = GetBlock(x, y, z);

        return block;
    }

    public Block GetBlock(int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            Vector3i regionalPosition = GetRegionalPosition(x, y, z);
            Vector3i region = GetRegionPosition(x, y, z);

            return regions[region.X, region.Y, region.Z].Blocks[regionalPosition.X, regionalPosition.Y, regionalPosition.Z];
        }

        return new Block(BlockType.none);
    }

    public void RemoveBlock(Vector3 position)
    {
        int x = (int)Math.Floor(position.X);
        int y = (int)Math.Floor(position.Y);
        int z = (int)Math.Ceiling(position.Z);

        Vector3i regionalPosition = GetRegionalPosition(x, y, z);
        Vector3i region = GetRegionPosition(x, y, z);

        Block block = new Block(regions[region.X, region.Y, region.Z].Blocks[regionalPosition.X, regionalPosition.Y, regionalPosition.Z].BlockType);

        regions[region.X, region.Y, region.Z].QueueForBuild(block);
        regions[region.X, region.Y, region.Z].Blocks[regionalPosition.X, regionalPosition.Y, regionalPosition.Z].BlockType = BlockType.none;

        lighting.BlockRemoved(block, x, y, z);
    }

    public void AddBlock(Block block, Vector3 position)
    {
        //position += new Vector3(0.5f, 0.5f, 0.5f);

        int x = (int)Math.Floor(position.X);
        int y = (int)Math.Floor(position.Y);
        int z = (int)Math.Ceiling(position.Z);

        AddBlock(block, x, y, z);
    }

    public void AddBlock(Block block, int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            Vector3i regionalPosition = GetRegionalPosition(x, y, z);
            Vector3i region = GetRegionPosition(x, y, z);

            regions[region.X, region.Y, region.Z].Blocks[regionalPosition.X, regionalPosition.Y, regionalPosition.Z].BlockType = block.BlockType;

            if (lighting != null)
            {
                lighting.BlockAdded(block, x, y, z);

                if (GetBlock(x, y, z).BlockType == BlockType.waterStill)
                {
                    regions[region.X, region.Y, region.Z].QueueForBuild(BufferType.Water);
                    fuilds.WaterQueue.Enqueue(new Flow(x, y, z, 16));
                }
                else
                {
                    regions[region.X, region.Y, region.Z].QueueForBuild(BufferType.Solid);
                }
            }
        }
    }

    public Vector3i GetRegionPosition(int x, int y, int z)
    {
        int regionx = x == 0 ? 0 : x / Variables.REGION_SIZE_X;
        int regiony = y == 0 ? 0 : y / Variables.REGION_SIZE_Y;
        int regionz = z == 0 ? 0 : z / Variables.REGION_SIZE_Z;

        return new Vector3i(regionx, regiony, regionz);
    }

    public Vector3i GetRegionalPosition(int x, int y, int z)
    {
        int regionx = x == 0 ? 0 : x / Variables.REGION_SIZE_X;
        int X = x % Variables.REGION_SIZE_X;

        int regiony = y == 0 ? 0 : y / Variables.REGION_SIZE_Y;
        int Y = y % Variables.REGION_SIZE_Y;

        int regionz = z == 0 ? 0 : z / Variables.REGION_SIZE_Z;
        int Z = z % Variables.REGION_SIZE_Z;

        return new Vector3i(X, Y, Z);
    }

    public void MakeDirty(BufferType buffer, int x, int y, int z)
    {
        Vector3i regionalPosition = GetRegionPosition(x, y, z);

        regions[regionalPosition.X, regionalPosition.Y, regionalPosition.Z].QueueForBuild(buffer);
    }

If you need any more of the source ill post it :D

Any ideas?

Thanks very much :)

Edit 1:

    public bool InBounds(int x, int y, int z)
    {
        if ((x < 0 || y < 0 || z < 0) ||
            x >= size.X || y >= size.Y || z >= size.Z)
        {
            return false;
        }

        return true;
    }

    public bool Exists(int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            int[] regionalPosition = GetRegionalPosition(x, y, z);
            int[] region = GetRegionPosition(x, y, z);

            return !(regions[region[0], region[1], region[2]].Blocks[regionalPosition[0], regionalPosition[1], regionalPosition[2]].BlockType == BlockType.none);
        }

        return false;
    }


    public void SetLight(int x, int y, int z, int light)
    {
        if (InBounds(x, y, z))
        {
            int[] regionalPosition = GetRegionalPosition(x, y, z);
            int[] region = GetRegionPosition(x, y, z);

            regions[region[0], region[1], region[2]].QueueForBuild(BufferType.All);
            regions[region[0], region[1], region[2]].Blocks[regionalPosition[0], regionalPosition[1], regionalPosition[2]].Light = (byte)light;
        }
    }

    public int GetLight(int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            // ARRAYS start from ZERO
            // LOGIC starts from ONE

            int[] regionalPosition = GetRegionalPosition(x, y, z);
            int[] region = GetRegionPosition(x, y, z);

            return regions[region[0], region[1], region[2]].Blocks[regionalPosition[0], regionalPosition[1], regionalPosition[2]].Light;
        }

        return -1;
    }

    public Block GetBlock(Vector3 position)
    {
        int x = (int)Math.Floor(position.X);
        int y = (int)Math.Floor(position.Y);
        int z = (int)Math.Ceiling(position.Z);

        Block block = GetBlock(x, y, z);

        return block;
    }

    public Block GetBlock(int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            int[] regionalPosition = GetRegionalPosition(x, y, z);
            int[] region = GetRegionPosition(x, y, z);

            return regions[region[0], region[1], region[2]].Blocks[regionalPosition[0], regionalPosition[1], regionalPosition[2]];
        }

        return new Block(BlockType.none);
    }

    public void RemoveBlock(Vector3 position)
    {
        int x = (int)Math.Floor(position.X);
        int y = (int)Math.Floor(position.Y);
        int z = (int)Math.Ceiling(position.Z);

        int[] regionalPosition = GetRegionalPosition(x, y, z);
        int[] region = GetRegionPosition(x, y, z);

        Block block = new Block(regions[region[0], region[1], region[2]].Blocks[regionalPosition[0], regionalPosition[1], regionalPosition[2]].BlockType);

        regions[region[0], region[1], region[2]].QueueForBuild(block);
        regions[region[0], region[1], region[2]].Blocks[regionalPosition[0], regionalPosition[1], regionalPosition[2]].BlockType = BlockType.none;

        lighting.BlockRemoved(block, x, y, z);
    }

    public void AddBlock(Block block, Vector3 position)
    {
        //position += new Vector3(0.5f, 0.5f, 0.5f);

        int x = (int)Math.Floor(position.X);
        int y = (int)Math.Floor(position.Y);
        int z = (int)Math.Ceiling(position.Z);

        AddBlock(block, x, y, z);
    }

    public void AddBlock(Block block, int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            int[] regionalPosition = GetRegionalPosition(x, y, z);
            int[] region = GetRegionPosition(x, y, z);

            regions[region[0], region[1], region[2]].Blocks[regionalPosition[0], regionalPosition[1], regionalPosition[2]].BlockType = block.BlockType;

            if (lighting != null)
            {
                lighting.BlockAdded(block, x, y, z);

                if (GetBlock(x, y, z).BlockType == BlockType.waterStill)
                {
                    regions[region[0], region[1], region[2]].QueueForBuild(BufferType.Water);
                    fuilds.WaterQueue.Enqueue(new Flow(x, y, z, 16));
                }
                else
                {
                    regions[region[0], region[1], region[2]].QueueForBuild(BufferType.Solid);
                }
            }
        }
    }

    public int[] GetRegionPosition(int x, int y, int z)
    {
        int regionx = x == 0 ? 0 : x / Variables.REGION_SIZE_X;
        int regiony = y == 0 ? 0 : y / Variables.REGION_SIZE_Y;
        int regionz = z == 0 ? 0 : z / Variables.REGION_SIZE_Z;

        return new int[] {regionx, regiony, regionz};
    }

    public int[] GetRegionalPosition(int x, int y, int z)
    {
        int regionx = x == 0 ? 0 : x / Variables.REGION_SIZE_X;
        int X = x % Variables.REGION_SIZE_X;

        int regiony = y == 0 ? 0 : y / Variables.REGION_SIZE_Y;
        int Y = y % Variables.REGION_SIZE_Y;

        int regionz = z == 0 ? 0 : z / Variables.REGION_SIZE_Z;
        int Z = z % Variables.REGION_SIZE_Z;

        return new int[] { regionx, regiony, regionz };
    }

    public void MakeDirty(BufferType buffer, int x, int y, int z)
    {
        int[] regionalPosition = GetRegionPosition(x, y, z);

        regions[regionalPosition[0], regionalPosition[1], regionalPosition[2]].QueueForBuild(buffer);
    }

    public void Draw(SpriteBatch spriteBatch)
    {
        blockRenderer.Draw(player, this);
        player.Draw(spriteBatch);
    }
}

Edit 2:

OK, here is the new code:

    public bool InBounds(int x, int y, int z)
    {
        if ((x < 0 || y < 0 || z < 0) ||
            x >= size.X || y >= size.Y || z >= size.Z)
        {
            return false;
        }

        return true;
    }

    public bool Exists(int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            int regionX, regionY, regionZ;
            int regionalX, regionalY, regionalZ;

            regionX = regionalX = x;
            regionY = regionalY = y;
            regionZ = regionalZ = z;

            GetRegionPosition(ref regionX, ref regionY, ref regionZ);
            GetRegionalPosition(ref regionalX, ref regionalY, ref regionalZ);

            return !(regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ].BlockType == BlockType.none);
        }

        return false;
    }


    public void SetLight(int x, int y, int z, int light)
    {
        if (InBounds(x, y, z))
        {
            int regionX, regionY, regionZ;
            int regionalX, regionalY, regionalZ;

            regionX = regionalX = x;
            regionY = regionalY = y;
            regionZ = regionalZ = z;

            GetRegionPosition(ref regionX, ref regionY, ref regionZ);
            GetRegionalPosition(ref regionalX, ref regionalY, ref regionalZ);

            regions[regionX, regionY, regionZ].QueueForBuild(BufferType.All);

            regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ].Light = (byte)light;
        }
    }

    public int GetLight(int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            // ARRAYS start from ZERO
            // LOGIC starts from ONE

            int regionX, regionY, regionZ;
            int regionalX, regionalY, regionalZ;

            regionX = regionalX = x;
            regionY = regionalY = y;
            regionZ = regionalZ = z;

            GetRegionPosition(ref regionX, ref regionY, ref regionZ);
            GetRegionalPosition(ref regionalX, ref regionalY, ref regionalZ);

            return regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ].Light;
        }

        return -1;
    }

    public Block GetBlock(Vector3 position)
    {
        int x = (int)Math.Floor(position.X);
        int y = (int)Math.Floor(position.Y);
        int z = (int)Math.Ceiling(position.Z);

        Block block = GetBlock(x, y, z);

        return block;
    }

    public Block GetBlock(int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            int regionX, regionY, regionZ;
            int regionalX, regionalY, regionalZ;

            regionX = regionalX = x;
            regionY = regionalY = y;
            regionZ = regionalZ = z;

            GetRegionPosition(ref regionX, ref regionY, ref regionZ);
            GetRegionalPosition(ref regionalX, ref regionalY, ref regionalZ);



            return regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ];
        }

        return new Block(BlockType.none);
    }

    public void RemoveBlock(Vector3 position)
    {
        int x = (int)Math.Floor(position.X);
        int y = (int)Math.Floor(position.Y);
        int z = (int)Math.Ceiling(position.Z);

        int regionX, regionY, regionZ;
        int regionalX, regionalY, regionalZ;

        regionX = regionalX = x;
        regionY = regionalY = y;
        regionZ = regionalZ = z;

        GetRegionPosition(ref regionX, ref regionY, ref regionZ);
        GetRegionalPosition(ref regionalX, ref regionalY, ref regionalZ);

        Block block = new Block(regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ].BlockType);

        regions[regionX, regionY, regionZ].QueueForBuild(block);
        regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ].BlockType = BlockType.none;

        lighting.BlockRemoved(block, x, y, z);
    }

    public void AddBlock(Block block, Vector3 position)
    {
        //position += new Vector3(0.5f, 0.5f, 0.5f);

        int x = (int)Math.Floor(position.X);
        int y = (int)Math.Floor(position.Y);
        int z = (int)Math.Ceiling(position.Z);

        AddBlock(block, x, y, z);
    }

    public void AddBlock(Block block, int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            int regionX, regionY, regionZ;
            int regionalX, regionalY, regionalZ;

            regionX = regionalX = x;
            regionY = regionalY = y;
            regionZ = regionalZ = z;

            GetRegionPosition(ref regionX, ref regionY, ref regionZ);
            GetRegionalPosition(ref regionalX, ref regionalY, ref regionalZ);

            regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ].BlockType = block.BlockType;

            if (lighting != null)
            {
                lighting.BlockAdded(block, x, y, z);

                if (GetBlock(x, y, z).BlockType == BlockType.waterStill)
                {
                    regions[regionX, regionY, regionZ].QueueForBuild(BufferType.Water);
                    fuilds.WaterQueue.Enqueue(new Flow(x, y, z, 16));
                }
                else
                {
                    regions[regionX, regionY, regionZ].QueueForBuild(BufferType.Solid);
                }
            }
        }
    }

    public void GetRegionPosition(ref int x, ref int y, ref int z)
    {
        x = x == 0 ? 0 : x / Variables.REGION_SIZE_X;
        y = y == 0 ? 0 : y / Variables.REGION_SIZE_Y;
        z = z == 0 ? 0 : z / Variables.REGION_SIZE_Z;
    }

    public void GetRegionalPosition(ref int x, ref int y, ref int z)
    {
        int regionx = x == 0 ? 0 : x / Variables.REGION_SIZE_X;
        x = x % Variables.REGION_SIZE_X;

        int regiony = y == 0 ? 0 : y / Variables.REGION_SIZE_Y;
        y = y % Variables.REGION_SIZE_Y;

        int regionz = z == 0 ? 0 : z / Variables.REGION_SIZE_Z;
        z = z % Variables.REGION_SIZE_Z;
    }

    public void MakeDirty(BufferType buffer, int x, int y, int z)
    {
        int regionX, regionY, regionZ;
        int regionalX, regionalY, regionalZ;

        regionX = regionalX = x;
        regionY = regionalY = y;
        regionZ = regionalZ = z;

        GetRegionalPosition(ref regionalX, ref regionalY, ref regionalZ);

        regions[regionalX, regionalY, regionalZ].QueueForBuild(buffer);
    }

But this still generates a similar report:

enter image description here

Edit 3:

    public bool InBounds(int x, int y, int z)
    {
        return !((x < 0 || y < 0 || z < 0) || x >= size.X || y >= size.Y || z >= size.Z);
    }

    public bool Exists(int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            int regionX, regionY, regionZ;
            int regionalX, regionalY, regionalZ;

            regionX = regionalX = x;
            regionY = regionalY = y;
            regionZ = regionalZ = z;

            GetRegionPosition(ref regionX, ref regionY, ref regionZ);
            GetRegionalPosition(ref regionalX, ref regionalY, ref regionalZ);

            return !(regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ].BlockType == BlockType.none);
        }

        return false;
    }


    public void SetLight(int x, int y, int z, int light)
    {
        if (InBounds(x, y, z))
        {
            int regionX, regionY, regionZ;
            int regionalX, regionalY, regionalZ;

            regionX = regionalX = x;
            regionY = regionalY = y;
            regionZ = regionalZ = z;

            GetRegionPosition(ref regionX, ref regionY, ref regionZ);
            GetRegionalPosition(ref regionalX, ref regionalY, ref regionalZ);

            regions[regionX, regionY, regionZ].QueueForBuild(BufferType.All);

            regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ].Light = (byte)light;
        }
    }

    public int GetLight(int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            // ARRAYS start from ZERO
            // LOGIC starts from ONE

            int regionX, regionY, regionZ;
            int regionalX, regionalY, regionalZ;

            regionX = regionalX = x;
            regionY = regionalY = y;
            regionZ = regionalZ = z;

            GetRegionPosition(ref regionX, ref regionY, ref regionZ);
            GetRegionalPosition(ref regionalX, ref regionalY, ref regionalZ);

            return regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ].Light;
        }

        return -1;
    }

    public Block GetBlock(Vector3 position)
    {
        int x = (int)Math.Floor(position.X);
        int y = (int)Math.Floor(position.Y);
        int z = (int)Math.Ceiling(position.Z);

        Block block = GetBlock(x, y, z);

        return block;
    }

    public Block GetBlock(int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            int regionX, regionY, regionZ;
            int regionalX, regionalY, regionalZ;

            regionX = regionalX = x;
            regionY = regionalY = y;
            regionZ = regionalZ = z;

            GetRegionPosition(ref regionX, ref regionY, ref regionZ);
            GetRegionalPosition(ref regionalX, ref regionalY, ref regionalZ);



            return regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ];
        }

        return new Block(BlockType.none);
    }

    public void RemoveBlock(Vector3 position)
    {
        int x = (int)Math.Floor(position.X);
        int y = (int)Math.Floor(position.Y);
        int z = (int)Math.Ceiling(position.Z);

        int regionX, regionY, regionZ;
        int regionalX, regionalY, regionalZ;

        regionX = regionalX = x;
        regionY = regionalY = y;
        regionZ = regionalZ = z;

        GetRegionPosition(ref regionX, ref regionY, ref regionZ);
        GetRegionalPosition(ref regionalX, ref regionalY, ref regionalZ);

        BlockType blockType = regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ].BlockType;

        regions[regionX, regionY, regionZ].QueueForBuild(blockType);
        regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ].BlockType = BlockType.none;

        lighting.BlockRemoved(blockType, x, y, z);
    }

    public void AddBlock(BlockType blockType, Vector3 position)
    {
        //position += new Vector3(0.5f, 0.5f, 0.5f);

        int x = (int)Math.Floor(position.X);
        int y = (int)Math.Floor(position.Y);
        int z = (int)Math.Ceiling(position.Z);

        AddBlock(blockType, x, y, z);
    }

    public void AddBlock(BlockType block, int x, int y, int z)
    {
        if (InBounds(x, y, z))
        {
            int regionX, regionY, regionZ;
            int regionalX, regionalY, regionalZ;

            regionX = regionalX = x;
            regionY = regionalY = y;
            regionZ = regionalZ = z;

            GetRegionPosition(ref regionX, ref regionY, ref regionZ);
            GetRegionalPosition(ref regionalX, ref regionalY, ref regionalZ);

            regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ].BlockType = block;

            if (lighting != null)
            {
                lighting.BlockAdded(block, x, y, z);

                if (GetBlock(x, y, z).BlockType == BlockType.waterStill)
                {
                    regions[regionX, regionY, regionZ].QueueForBuild(BufferType.Water);
                    fuilds.WaterQueue.Enqueue(new Flow(x, y, z, 16));
                }
                else
                {
                    regions[regionX, regionY, regionZ].QueueForBuild(BufferType.Solid);
                }
            }
        }
    }

    public void GetRegionPosition(ref int x, ref int y, ref int z)
    {
        x = x / Variables.REGION_SIZE_X;
        y = y / Variables.REGION_SIZE_Y;
        z = z / Variables.REGION_SIZE_Z;
    }

    public void GetRegionalPosition(ref int x, ref int y, ref int z)
    {
        x = x % Variables.REGION_SIZE_X;

        y = y % Variables.REGION_SIZE_Y;

        z = z % Variables.REGION_SIZE_Z;
    }

    public void MakeDirty(BufferType buffer, int x, int y, int z)
    {
        int regionX, regionY, regionZ;
        int regionalX, regionalY, regionalZ;

        regionX = regionalX = x;
        regionY = regionalY = y;
        regionZ = regionalZ = z;

        GetRegionalPosition(ref regionalX, ref regionalY, ref regionalZ);

        regions[regionalX, regionalY, regionalZ].QueueForBuild(buffer);
    }

enter image description here

enter image description here

share|improve this question
add comment

1 Answer

up vote 6 down vote accepted

Ok, it's pretty simple. The good bit is, once you fix this stuff it'll perform a couple of orders of magnitude better ;)

The first rule is that for functions that are frequently used and perform read operations, you can't afford to allocate memory if you want your game to actually function or perform at an interactive level. You can't afford to allocate a vector every time you want to find out which part of the array is storing the block you want.

GetRegionalPosition/GetRegionPosition/GetBlock

None of these should ever allocate memory on the heap.

If you have a block of voxels, just use a 1 dimensional array, and you can use something simple for the location within that block:

width * height * z + height * x + y

That will be an integer location, and you won't have to pass around objects for the location. Since integers are primitives, they're allocated on the stack, so they're safe, temporary objects are the enemy.

An improvement of this is to use shift operators if the size of your chunks are powers of two. I'm happy to walk you through that later, but first we need to get rid of those allocations.

It's ok to allocate objects in response to use input, or for non-frequent events, but it'll come back to bite you if it's occurring in any frequently running code.

If you're writing a game on a garbage collected VM (like C#/Java), you should feel physical pain at any point that you allocate an object.

GetBlock

At any point you want a class that represents the block, you really cant afford to allocate it everytime. In order to avoid allocations, the only sane way to approach it is to have a single class instance for each block type, and all methods that use it and depend on it's location pass in the (x,y,z) that the block is at. To go with this you should also have an array in static space that allows you to lookup blocks based on their ids.

Happy to clarify anything I've skipped over or written confusingly.

In Response to Edit #3

In "public void AddBlock(BlockType block, int x, int y, int z)"

regions[regionX, regionY, regionZ].Blocks[regionalX, regionalY, regionalZ].BlockType = block;

I'm guessing this block object has a whole bunch of methods for block type, lighting and extra data etc. This means you're storing thousands of individual block objects. Your garbage collector hates you for this, and it causes an extra level of indirection (chasing pointers) which is a bad thing for memory locatlity.

At some point you're going to want to switch to just using a handful of primitive arrays:

Different language, but same deal:

var blockIds = new Array[Byte](Chunk.blockSize)
var data = new Array[Byte](Chunk.blockSize)

var sunLight = new Array[Byte](Chunk.blockSize)
var torchLight =new Array[Byte](Chunk.blockSize)

The results from the fluid flow profile aren't surprising. Any local water modal is a can of worms in terms of run time complexity. There isn't a guarantee that you can have a water model like that and have decent performance at the same time.

world.addBlock taking 10% (which also involves your lighting system) doesn't look too bad.

I'd move to primitive arrays away from objects and see how much of an improvement that gives you. I'd also move to having a placeholder empty Region that returns only empty blocks so you can remove inBounds checking from your common methods. As part of this, you'd increase your region array to be always have padding on the sides, and slot the placeholder empty region in to all of the non-loaded slots.

This means that all of your actual world would be surrounded by the placeholder empty region, and you would never need to check bounds, removing the last bit of branching from your read operations.

share|improve this answer
    
OK, I think I understand what you are getting at... So basicly I just have to use primitive types like an array of interger. Ill post what I mean in the main post, the strange thing is when I change everything to arrays the world generation is not working properly, can you see anything I have done wrong and if I am going about doing this correctly? –  Darestium Feb 4 '12 at 3:41
    
Arrays aren't primitives. Arrays are an object that houses primitives. The rule is that you're not allowed to use the "new" word ;) –  Michael Feb 4 '12 at 3:45
    
OK, posted some new (haha) code above without using the new keyword :)... But it appears be even more so CPU intensive. –  Darestium Feb 4 '12 at 4:44
    
There's still a bunch I can point out, but first. If there's work to be done, the CPU should always be at 100%. What FPS are you getting, and is vsync off or on? –  Michael Feb 4 '12 at 5:00
    
vsync is off, I only get lag when I place blocks such as lava and water, and occasionally normal blocks. When I place water the fps gets as low as 15fps and generally the fps - on average - is at 500fps. If would would like ill post the water flowing code. –  Darestium Feb 4 '12 at 5:09
show 7 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.