Move the generation of the multi-resolution map tiles off the main

region creation thread. For varregions or simulators with many regions,
this will speed up simulator startup and elimiate some thread timeout
warnings.
bullet-2.82
Robert Adams 2014-05-31 14:21:39 -07:00
parent 0300ec45eb
commit a2ea844494
1 changed files with 67 additions and 17 deletions

View File

@ -36,6 +36,7 @@ using System.Drawing.Imaging;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Reflection; using System.Reflection;
using System.Threading;
using Nini.Config; using Nini.Config;
using log4net; using log4net;
@ -53,6 +54,7 @@ namespace OpenSim.Services.MapImageService
private static readonly ILog m_log = private static readonly ILog m_log =
LogManager.GetLogger( LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType); MethodBase.GetCurrentMethod().DeclaringType);
private string LogHeader = "[MAP IMAGE SERVICE]";
private const int ZOOM_LEVELS = 8; private const int ZOOM_LEVELS = 8;
private const int IMAGE_WIDTH = 256; private const int IMAGE_WIDTH = 256;
@ -114,7 +116,7 @@ namespace OpenSim.Services.MapImageService
} }
} }
return UpdateMultiResolutionFiles(x, y, out reason); return UpdateMultiResolutionFilesAsync(x, y, out reason);
} }
public bool RemoveMapTile(int x, int y, out string reason) public bool RemoveMapTile(int x, int y, out string reason)
@ -136,33 +138,81 @@ namespace OpenSim.Services.MapImageService
} }
} }
return UpdateMultiResolutionFiles(x, y, out reason); return UpdateMultiResolutionFilesAsync(x, y, out reason);
} }
private bool UpdateMultiResolutionFiles(int x, int y, out string reason) // When large varregions start up, they can send piles of new map tiles. This causes
// this multi-resolution routine to be called a zillion times an causes much CPU
// time to be spent creating multi-resolution tiles that will be replaced when
// the next maptile arrives.
private class mapToMultiRez
{
public int xx;
public int yy;
public mapToMultiRez(int pX, int pY)
{
xx = pX;
yy = pY;
}
};
private Queue<mapToMultiRez> multiRezToBuild = new Queue<mapToMultiRez>();
private bool UpdateMultiResolutionFilesAsync(int x, int y, out string reason)
{ {
reason = String.Empty; reason = String.Empty;
lock (m_Sync) lock (multiRezToBuild)
{ {
// Stitch seven more aggregate tiles together // m_log.DebugFormat("{0} UpdateMultiResolutionFilesAsync: scheduling update for <{1},{2}>", LogHeader, x, y);
for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++) multiRezToBuild.Enqueue(new mapToMultiRez(x, y));
{ if (multiRezToBuild.Count == 1)
// Calculate the width (in full resolution tiles) and bottom-left Util.FireAndForget(DoUpdateMultiResolutionFilesAsync);
// corner of the current zoom level }
int width = (int)Math.Pow(2, (double)(zoomLevel - 1));
int x1 = x - (x % width);
int y1 = y - (y % width);
if (!CreateTile(zoomLevel, x1, y1)) return true;
}
private void DoUpdateMultiResolutionFilesAsync(object o)
{
// This sleep causes the FireAndForget thread to be different than the invocation thread.
// It also allows other tiles to be uploaded so the multi-rez images are more likely
// to be correct.
Thread.Sleep(1 * 1000);
while (multiRezToBuild.Count > 0)
{
mapToMultiRez toMultiRez = null;
lock (multiRezToBuild)
{
if (multiRezToBuild.Count > 0)
toMultiRez = multiRezToBuild.Dequeue();
}
if (toMultiRez != null)
{
int x = toMultiRez.xx;
int y = toMultiRez.yy;
// m_log.DebugFormat("{0} DoUpdateMultiResolutionFilesAsync: doing build for <{1},{2}>", LogHeader, x, y);
// Stitch seven more aggregate tiles together
for (uint zoomLevel = 2; zoomLevel <= ZOOM_LEVELS; zoomLevel++)
{ {
m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0},{1} at zoom level {1}", x, y, zoomLevel); // Calculate the width (in full resolution tiles) and bottom-left
reason = string.Format("Map tile at zoom level {0} failed", zoomLevel); // corner of the current zoom level
return false; int width = (int)Math.Pow(2, (double)(zoomLevel - 1));
int x1 = x - (x % width);
int y1 = y - (y % width);
lock (m_Sync) // must lock the reading and writing of the maptile files
{
if (!CreateTile(zoomLevel, x1, y1))
{
m_log.WarnFormat("[MAP IMAGE SERVICE]: Unable to create tile for {0},{1} at zoom level {1}", x, y, zoomLevel);
return;
}
}
} }
} }
} }
return true; return;
} }
public byte[] GetMapTile(string fileName, out string format) public byte[] GetMapTile(string fileName, out string format)