mirror of
https://github.com/opensim/opensim.git
synced 2026-08-06 01:06:30 +08:00
on per client terrain taint control replace bad 2d bool array by a bitarray. 1d bool could be another option. bitarray uses a lot less mem but a bit more cpu, except on full set/clear, less mem is also less cpu cache pressure so lets use it, specially on linear scans on X
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
@@ -98,70 +99,89 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
// patch packet is queued to the client, the bit for that patch is set to 'false'.
|
||||
private class PatchUpdates
|
||||
{
|
||||
private bool[,] updated; // for each patch, whether it needs to be sent to this client
|
||||
private BitArray updated; // for each patch, whether it needs to be sent to this client
|
||||
private int updateCount; // number of patches that need to be sent
|
||||
public ScenePresence Presence; // a reference to the client to send to
|
||||
public bool sendAll;
|
||||
public int sendAllcurrentX;
|
||||
public int sendAllcurrentY;
|
||||
|
||||
private int xsize;
|
||||
private int ysize;
|
||||
|
||||
public PatchUpdates(TerrainData terrData, ScenePresence pPresence)
|
||||
{
|
||||
updated = new bool[terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize];
|
||||
updateCount = 0;
|
||||
xsize = terrData.SizeX / Constants.TerrainPatchSize;
|
||||
ysize = terrData.SizeY / Constants.TerrainPatchSize;
|
||||
updated = new BitArray(xsize * ysize, true);
|
||||
updateCount = xsize * ysize;
|
||||
Presence = pPresence;
|
||||
// Initially, send all patches to the client
|
||||
SetAll(true);
|
||||
sendAll = true;
|
||||
sendAllcurrentX = 0;
|
||||
sendAllcurrentY = 0;
|
||||
}
|
||||
|
||||
// Returns 'true' if there are any patches marked for sending
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool HasUpdates()
|
||||
{
|
||||
return (updateCount > 0);
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public void SetByXY(int x, int y, bool state)
|
||||
{
|
||||
this.SetByPatch(x / Constants.TerrainPatchSize, y / Constants.TerrainPatchSize, state);
|
||||
SetByPatch(x / Constants.TerrainPatchSize , y / Constants.TerrainPatchSize, state);
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public bool GetByPatch(int patchX, int patchY)
|
||||
{
|
||||
return updated[patchX, patchY];
|
||||
return updated[patchX + xsize * patchY];
|
||||
}
|
||||
|
||||
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
|
||||
public void SetByPatch(int patchX, int patchY, bool state)
|
||||
{
|
||||
bool prevState = updated[patchX, patchY];
|
||||
if (!prevState && state)
|
||||
updateCount++;
|
||||
if (prevState && !state)
|
||||
updateCount--;
|
||||
updated[patchX, patchY] = state;
|
||||
int indx = patchX + xsize * patchY;
|
||||
bool prevState = updated[indx];
|
||||
updated[indx] = state;
|
||||
if (state)
|
||||
{
|
||||
if (!prevState)
|
||||
updateCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (prevState)
|
||||
updateCount--;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetAll(bool state)
|
||||
{
|
||||
updateCount = 0;
|
||||
for (int xx = 0; xx < updated.GetLength(0); xx++)
|
||||
for (int yy = 0; yy < updated.GetLength(1); yy++)
|
||||
updated[xx, yy] = state;
|
||||
updated.SetAll(state);
|
||||
|
||||
if (state)
|
||||
updateCount = updated.GetLength(0) * updated.GetLength(1);
|
||||
{
|
||||
sendAll = true;
|
||||
updateCount = xsize * ysize;
|
||||
}
|
||||
else updateCount = 0;
|
||||
|
||||
sendAllcurrentX = 0;
|
||||
sendAllcurrentY = 0;
|
||||
sendAll = true;
|
||||
}
|
||||
|
||||
// Logically OR's the terrain data's patch taint map into this client's update map.
|
||||
public void SetAll(TerrainData terrData)
|
||||
{
|
||||
if (updated.GetLength(0) != (terrData.SizeX / Constants.TerrainPatchSize)
|
||||
|| updated.GetLength(1) != (terrData.SizeY / Constants.TerrainPatchSize))
|
||||
if (xsize != (terrData.SizeX / Constants.TerrainPatchSize)
|
||||
|| ysize != (terrData.SizeY / Constants.TerrainPatchSize))
|
||||
{
|
||||
throw new Exception(
|
||||
String.Format("{0} PatchUpdates.SetAll: patch array not same size as terrain. arr=<{1},{2}>, terr=<{3},{4}>",
|
||||
LogHeader, updated.GetLength(0), updated.GetLength(1),
|
||||
LogHeader, xsize, ysize,
|
||||
terrData.SizeX / Constants.TerrainPatchSize, terrData.SizeY / Constants.TerrainPatchSize)
|
||||
);
|
||||
}
|
||||
@@ -173,7 +193,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
// Only set tainted. The patch bit may be set if the patch was to be sent later.
|
||||
if (terrData.IsTaintedAt(xx, yy, false))
|
||||
{
|
||||
this.SetByXY(xx, yy, true);
|
||||
SetByXY(xx, yy, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1119,48 +1139,33 @@ namespace OpenSim.Region.CoreModules.World.Terrain
|
||||
{
|
||||
foreach (PatchUpdates pups in m_perClientPatchUpdates.Values)
|
||||
{
|
||||
if(pups.Presence.IsDeleted)
|
||||
if(pups.Presence.IsDeleted || !pups.HasUpdates() || !pups.Presence.ControllingClient.CanSendLayerData())
|
||||
continue;
|
||||
|
||||
// limit rate acording to udp land queue state
|
||||
if (!pups.Presence.ControllingClient.CanSendLayerData())
|
||||
continue;
|
||||
|
||||
if (pups.HasUpdates())
|
||||
if (m_sendTerrainUpdatesByViewDistance)
|
||||
{
|
||||
if (m_sendTerrainUpdatesByViewDistance)
|
||||
// There is something that could be sent to this client.
|
||||
List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
|
||||
if (toSend.Count > 0)
|
||||
{
|
||||
// There is something that could be sent to this client.
|
||||
List<PatchesToSend> toSend = GetModifiedPatchesInViewDistance(pups);
|
||||
if (toSend.Count > 0)
|
||||
// m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}",
|
||||
// LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName);
|
||||
// Sort the patches to send by the distance from the presence
|
||||
toSend.Sort();
|
||||
int[] patchPieces = new int[toSend.Count * 2];
|
||||
int pieceIndex = 0;
|
||||
foreach (PatchesToSend pts in toSend)
|
||||
{
|
||||
// m_log.DebugFormat("{0} CheckSendingPatchesToClient: sending {1} patches to {2} in region {3}",
|
||||
// LogHeader, toSend.Count, pups.Presence.Name, m_scene.RegionInfo.RegionName);
|
||||
// Sort the patches to send by the distance from the presence
|
||||
toSend.Sort();
|
||||
/*
|
||||
foreach (PatchesToSend pts in toSend)
|
||||
{
|
||||
pups.Presence.ControllingClient.SendLayerData(pts.PatchX, pts.PatchY, null);
|
||||
// presence.ControllingClient.SendLayerData(xs.ToArray(), ys.ToArray(), null, TerrainPatch.LayerType.Land);
|
||||
}
|
||||
*/
|
||||
|
||||
int[] patchPieces = new int[toSend.Count * 2];
|
||||
int pieceIndex = 0;
|
||||
foreach (PatchesToSend pts in toSend)
|
||||
{
|
||||
patchPieces[pieceIndex++] = pts.PatchX;
|
||||
patchPieces[pieceIndex++] = pts.PatchY;
|
||||
}
|
||||
pups.Presence.ControllingClient.SendLayerData(patchPieces);
|
||||
patchPieces[pieceIndex++] = pts.PatchX;
|
||||
patchPieces[pieceIndex++] = pts.PatchY;
|
||||
}
|
||||
if (pups.sendAll && toSend.Count < 1024)
|
||||
SendAllModifiedPatchs(pups);
|
||||
pups.Presence.ControllingClient.SendLayerData(patchPieces);
|
||||
}
|
||||
else
|
||||
if (pups.sendAll && toSend.Count < 1024)
|
||||
SendAllModifiedPatchs(pups);
|
||||
}
|
||||
else
|
||||
SendAllModifiedPatchs(pups);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user