Permalink
Browse files

Optimize msDrawRasterGDAL_16BitClassification() runtime.

The creation of buckets takes a significant time when they are many, and many classes
as well. When iterating over buckets, a faster strategy is to reuse first the last
used class index.
  • Loading branch information...
rouault committed Jan 5, 2017
1 parent 19d77c5 commit adf3383e52a91ded988b80a4b296a88c6bdf941c
Showing with 60 additions and 20 deletions.
  1. +19 −2 mapdrawgdal.c
  2. +40 −18 mapraster.c
  3. +1 −0 mapserver.h
View
@@ -32,7 +32,7 @@
#include "mapserver.h"
#include "mapresample.h"
#include "mapthread.h"
-
+#include "maptime.h"
extern int InvGeoTransform( double *gt_in, double *gt_out );
@@ -1717,6 +1717,9 @@ msDrawRasterLayerGDAL_16BitClassification(
unsigned char *rb_cmap[4];
CPLErr eErr;
rasterBufferObj *mask_rb = NULL;
+ int lastC;
+ struct mstimeval starttime, endtime;
+
if(layer->mask) {
int ret;
layerObj *maskLayer = GET_LAYER(map, msGetLayerIndex(map,layer->mask));
@@ -1875,14 +1878,21 @@ msDrawRasterLayerGDAL_16BitClassification(
rb_cmap[2] = (unsigned char *) msSmallCalloc(1,nBucketCount);
rb_cmap[3] = (unsigned char *) msSmallCalloc(1,nBucketCount);
+
+ if(layer->debug >= MS_DEBUGLEVEL_TUNING) {
+ msGettimeofday(&starttime, NULL);
+ }
+
+ lastC = -1;
for(i=0; i < nBucketCount; i++) {
double dfOriginalValue;
cmap[i] = -1;
dfOriginalValue = (i+0.5) / dfScaleRatio + dfScaleMin;
- c = msGetClass_FloatRGB(layer, (float) dfOriginalValue, -1, -1, -1);
+ c = msGetClass_FloatRGB_WithFirstClassToTry(layer, (float) dfOriginalValue, -1, -1, -1, lastC);
+ lastC = c;
if( c != -1 ) {
int s;
@@ -1904,6 +1914,13 @@ msDrawRasterLayerGDAL_16BitClassification(
}
}
+ if(layer->debug >= MS_DEBUGLEVEL_TUNING) {
+ msGettimeofday(&endtime, NULL);
+ msDebug("msDrawRasterGDAL_16BitClassification() bucket creation time: %.3fs\n",
+ (endtime.tv_sec+endtime.tv_usec/1.0e6)-
+ (starttime.tv_sec+starttime.tv_usec/1.0e6) );
+ }
+
/* ==================================================================== */
/* Now process the data, applying to the working imageObj. */
/* ==================================================================== */
View
@@ -60,7 +60,7 @@ extern parseResultObj yypresult; /* result of parsing, true/false */
/* msGetClass_String() */
/************************************************************************/
-static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixel_value )
+static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixel_value, int firstClassToTry )
{
int i;
@@ -80,9 +80,18 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
/* Setup values list for expressions. */
/* -------------------------------------------------------------------- */
numitems = 4;
- sprintf( red_value, "%d", color->red );
- sprintf( green_value, "%d", color->green );
- sprintf( blue_value, "%d", color->blue );
+ if( color->red == -1 && color->green == -1 && color->blue == -1 )
+ {
+ strcpy(red_value, "-1");
+ strcpy(green_value, "-1");
+ strcpy(blue_value, "-1");
+ }
+ else
+ {
+ sprintf( red_value, "%d", color->red );
+ sprintf( green_value, "%d", color->green );
+ sprintf( blue_value, "%d", color->blue );
+ }
item_values[0] = (char *)pixel_value;
item_values[1] = red_value;
@@ -92,18 +101,24 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
/* -------------------------------------------------------------------- */
/* Loop over classes till we find a match. */
/* -------------------------------------------------------------------- */
- for(i=0; i<layer->numclasses; i++) {
+ for(i= (firstClassToTry < 0 ) ? 0 : -1; i<layer->numclasses; i++) {
+
+ int idx = i;
+ if( i < 0 )
+ idx = firstClassToTry;
+ else if( i == firstClassToTry )
+ continue;
/* check for correct classgroup, if set */
- if ( layer->class[i]->group && layer->classgroup &&
- strcasecmp(layer->class[i]->group, layer->classgroup) != 0 )
+ if ( layer->class[idx]->group && layer->classgroup &&
+ strcasecmp(layer->class[idx]->group, layer->classgroup) != 0 )
continue;
/* Empty expression - always matches */
- if (layer->class[i]->expression.string == NULL)
+ if (layer->class[idx]->expression.string == NULL)
return(i);
- switch(layer->class[i]->expression.type) {
+ switch(layer->class[idx]->expression.type) {
/* -------------------------------------------------------------------- */
/* Simple string match */
@@ -114,22 +129,22 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
while( *tmpstr1 == ' ' )
tmpstr1++;
- if(strcmp(layer->class[i]->expression.string, tmpstr1) == 0) return(i); /* matched */
+ if(strcmp(layer->class[idx]->expression.string, tmpstr1) == 0) return(idx); /* matched */
break;
/* -------------------------------------------------------------------- */
/* Regular expression. Rarely used for raster. */
/* -------------------------------------------------------------------- */
case(MS_REGEX):
- if(!layer->class[i]->expression.compiled) {
- if(ms_regcomp(&(layer->class[i]->expression.regex), layer->class[i]->expression.string, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { /* compile the expression */
+ if(!layer->class[idx]->expression.compiled) {
+ if(ms_regcomp(&(layer->class[idx]->expression.regex), layer->class[idx]->expression.string, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { /* compile the expression */
msSetError(MS_REGEXERR, "Invalid regular expression.", "msGetClass()");
return(-1);
}
- layer->class[i]->expression.compiled = MS_TRUE;
+ layer->class[idx]->expression.compiled = MS_TRUE;
}
- if(ms_regexec(&(layer->class[i]->expression.regex), pixel_value, 0, NULL, 0) == 0) return(i); /* got a match */
+ if(ms_regexec(&(layer->class[idx]->expression.regex), pixel_value, 0, NULL, 0) == 0) return(idx); /* got a match */
break;
/* -------------------------------------------------------------------- */
@@ -139,7 +154,7 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
int status;
parseObj p;
shapeObj dummy_shape;
- expressionObj *expression = &(layer->class[i]->expression);
+ expressionObj *expression = &(layer->class[idx]->expression);
dummy_shape.numvalues = numitems;
dummy_shape.values = item_values;
@@ -160,7 +175,7 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
}
if( p.result.intval )
- return i;
+ return idx;
break;
}
}
@@ -179,7 +194,7 @@ int msGetClass(layerObj *layer, colorObj *color, int colormap_index)
snprintf( pixel_value, sizeof(pixel_value), "%d", colormap_index );
- return msGetClass_String( layer, color, pixel_value );
+ return msGetClass_String( layer, color, pixel_value, -1 );
}
/************************************************************************/
@@ -190,6 +205,13 @@ int msGetClass(layerObj *layer, colorObj *color, int colormap_index)
/************************************************************************/
int msGetClass_FloatRGB(layerObj *layer, float fValue, int red, int green, int blue )
+{
+ return msGetClass_FloatRGB_WithFirstClassToTry(
+ layer, fValue, red, green, blue, -1);
+}
+
+
+int msGetClass_FloatRGB_WithFirstClassToTry(layerObj *layer, float fValue, int red, int green, int blue, int firstClassToTry )
{
char pixel_value[100];
colorObj color;
@@ -200,7 +222,7 @@ int msGetClass_FloatRGB(layerObj *layer, float fValue, int red, int green, int b
snprintf( pixel_value, sizeof(pixel_value), "%18g", fValue );
- return msGetClass_String( layer, &color, pixel_value );
+ return msGetClass_String( layer, &color, pixel_value, firstClassToTry );
}
#if defined(USE_GDAL)
View
@@ -2589,6 +2589,7 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char
MS_DLL_EXPORT int msGetClass(layerObj *layer, colorObj *color, int colormap_index);
MS_DLL_EXPORT int msGetClass_FloatRGB(layerObj *layer, float fValue,
int red, int green, int blue );
+ int msGetClass_FloatRGB_WithFirstClassToTry(layerObj *layer, float fValue, int red, int green, int blue, int firstClassToTry );
/* in mapdrawgdal.c */
MS_DLL_EXPORT int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb, void *hDSVoid );

0 comments on commit adf3383

Please sign in to comment.