* Adds console command, 'predecode-j2k <number of threads>' to load all of the texture assets from the scene and decode the j2k layer data to cache. The work is split between the number of threads you specify. A good number of threads value is the number of cores on your machine minus 1.

* Increases the number of ImageDataPackets we send per PriorityQueue pop and tweak it so that the number of packets is ( (2 * decode level) + 1 ) * 2, and (((2 * (5-decode level)) + 1) * 2).  The first one sends more data for low quality textures, the second one sends more data for high quality textures.
0.6.3-post-fixes
Teravus Ovares 2009-01-25 04:34:00 +00:00
parent 676b7c1073
commit 76206543e8
4 changed files with 153 additions and 2 deletions

View File

@ -496,6 +496,16 @@ namespace OpenSim
case "reset":
Reset(cmdparams);
break;
case "predecode-j2k":
if (cmdparams.Length > 0)
{
m_sceneManager.CacheJ2kDecode(Convert.ToInt32(cmdparams[0]));
}
else
{
m_sceneManager.CacheJ2kDecode(1);
}
break;
default:
string[] tmpPluginArgs = new string[cmdparams.Length + 1];
@ -688,6 +698,7 @@ namespace OpenSim
m_console.Notice("login-enable - Allows login at sim level");
m_console.Notice("login-disable - Disable login at sim level");
m_console.Notice("login-status - Show the actual login status");
m_console.Notice("predecode-j2k - Precache assets,decode j2k layerdata, First parameter is threads to use");
ShowPluginCommandsHelp(CombineParams(helpArgs, 0), m_console);

View File

@ -230,12 +230,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
else if (!process.data.J2KDecodeWaiting)
{
// Send more data at a time for higher discard levels
for (int i = 0; i < (2*(5 - process.data.DiscardLevel) + 1)*2; i++)
bool done = false;
for (int i = 0; i < (2*(process.data.DiscardLevel) + 1)*2; i++)
if (!process.data.SendPacket(m_client))
{
done = true;
pq[h] -= (500000*i);
break;
}
if (!done)
{
for (int i = 0; i < (2 * (5- process.data.DiscardLevel) + 1) * 2; i++)
if (!process.data.SendPacket(m_client))
{
done = true;
pq[h] -= (500000 * i);
break;
}
}
}
// If the priority is less then -4 billion, the client has forgotten about it, pop it off
if (pq[h] < -400000000)

View File

@ -236,7 +236,8 @@ namespace OpenSim.Region.Environment.Modules.Agent.TextureSender
// Cache Decoded layers
lock (m_cacheddecode)
{
m_cacheddecode.Add(AssetId, layers);
if (!m_cacheddecode.ContainsKey(AssetId))
m_cacheddecode.Add(AssetId, layers);
}

View File

@ -547,5 +547,132 @@ namespace OpenSim.Region.Environment.Scenes
{
m_localScenes.ForEach(action);
}
public void CacheJ2kDecode(int threads)
{
if (threads < 1) threads = 1;
IJ2KDecoder m_decoder = m_localScenes[0].RequestModuleInterface<IJ2KDecoder>();
List<UUID> assetRequestList = new List<UUID>();
#region AssetGathering!
foreach (Scene scene in m_localScenes)
{
List<EntityBase> entitles = scene.GetEntities();
foreach (EntityBase entity in entitles)
{
if (entity is SceneObjectGroup)
{
SceneObjectGroup sog = (SceneObjectGroup) entity;
foreach (SceneObjectPart part in sog.Children.Values)
{
if (part.Shape != null)
{
if (part.Shape.TextureEntry.Length > 0)
{
OpenMetaverse.Primitive.TextureEntry te =
new Primitive.TextureEntry(part.Shape.TextureEntry, 0,
part.Shape.TextureEntry.Length);
if (te.DefaultTexture != null) // this has been null for some reason...
{
if (te.DefaultTexture.TextureID != UUID.Zero)
assetRequestList.Add(te.DefaultTexture.TextureID);
}
for (int i=0; i<te.FaceTextures.Length; i++)
{
if (te.FaceTextures[i] != null)
{
if (te.FaceTextures[i].TextureID != UUID.Zero)
{
assetRequestList.Add(te.FaceTextures[i].TextureID);
}
}
}
}
if (part.Shape.SculptTexture != UUID.Zero)
{
assetRequestList.Add(part.Shape.SculptTexture);
}
}
}
}
}
}
#endregion
int entries_per_thread = (assetRequestList.Count/threads) + 1;
UUID[] arrAssetRequestList = assetRequestList.ToArray();
int currpos = 0;
List<UUID[]> arrvalus = new List<UUID[]>();
//split into separate arrays
for (int j=0;j<threads;j++)
{
List<UUID> val = new List<UUID>();
for (int k=j*entries_per_thread; k < ((j+1)* entries_per_thread);k++)
{
if (k < arrAssetRequestList.Length)
{
val.Add(arrAssetRequestList[k]);
}
}
arrvalus.Add(val.ToArray());
}
for (int l=0;l<arrvalus.Count;l++)
{
DecodeThreadContents threadworkItem = new DecodeThreadContents();
threadworkItem.sn = m_localScenes[0];
threadworkItem.j2kdecode = m_decoder;
threadworkItem.arrassets = arrvalus[l];
System.Threading.Thread decodethread =
new System.Threading.Thread(new System.Threading.ParameterizedThreadStart(threadworkItem.run));
threadworkItem.SetThread(decodethread);
decodethread.Priority = System.Threading.ThreadPriority.Lowest;
decodethread.Name = "J2kCacheDecodeThread_" + l+1;
ThreadTracker.Add(decodethread);
decodethread.Start();
}
}
}
public class DecodeThreadContents
{
public Scene sn;
public UUID[] arrassets;
public IJ2KDecoder j2kdecode;
private System.Threading.Thread thisthread;
public void run( object o)
{
for (int i=0;i<arrassets.Length;i++)
{
AssetBase ab = sn.AssetCache.GetAsset(arrassets[i], true);
if (ab != null && ab.Data != null)
{
j2kdecode.syncdecode(arrassets[i], ab.Data);
}
}
ThreadTracker.Remove(thisthread);
}
public void SetThread(System.Threading.Thread thr)
{
thisthread = thr;
}
}
}