Skip to content

Commit adf3383

Browse files
committed
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.
1 parent 19d77c5 commit adf3383

File tree

3 files changed

+60
-20
lines changed

3 files changed

+60
-20
lines changed

Diff for: mapdrawgdal.c

+19-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
#include "mapserver.h"
3333
#include "mapresample.h"
3434
#include "mapthread.h"
35-
35+
#include "maptime.h"
3636

3737

3838
extern int InvGeoTransform( double *gt_in, double *gt_out );
@@ -1717,6 +1717,9 @@ msDrawRasterLayerGDAL_16BitClassification(
17171717
unsigned char *rb_cmap[4];
17181718
CPLErr eErr;
17191719
rasterBufferObj *mask_rb = NULL;
1720+
int lastC;
1721+
struct mstimeval starttime, endtime;
1722+
17201723
if(layer->mask) {
17211724
int ret;
17221725
layerObj *maskLayer = GET_LAYER(map, msGetLayerIndex(map,layer->mask));
@@ -1875,14 +1878,21 @@ msDrawRasterLayerGDAL_16BitClassification(
18751878
rb_cmap[2] = (unsigned char *) msSmallCalloc(1,nBucketCount);
18761879
rb_cmap[3] = (unsigned char *) msSmallCalloc(1,nBucketCount);
18771880

1881+
1882+
if(layer->debug >= MS_DEBUGLEVEL_TUNING) {
1883+
msGettimeofday(&starttime, NULL);
1884+
}
1885+
1886+
lastC = -1;
18781887
for(i=0; i < nBucketCount; i++) {
18791888
double dfOriginalValue;
18801889

18811890
cmap[i] = -1;
18821891

18831892
dfOriginalValue = (i+0.5) / dfScaleRatio + dfScaleMin;
18841893

1885-
c = msGetClass_FloatRGB(layer, (float) dfOriginalValue, -1, -1, -1);
1894+
c = msGetClass_FloatRGB_WithFirstClassToTry(layer, (float) dfOriginalValue, -1, -1, -1, lastC);
1895+
lastC = c;
18861896
if( c != -1 ) {
18871897
int s;
18881898

@@ -1904,6 +1914,13 @@ msDrawRasterLayerGDAL_16BitClassification(
19041914
}
19051915
}
19061916

1917+
if(layer->debug >= MS_DEBUGLEVEL_TUNING) {
1918+
msGettimeofday(&endtime, NULL);
1919+
msDebug("msDrawRasterGDAL_16BitClassification() bucket creation time: %.3fs\n",
1920+
(endtime.tv_sec+endtime.tv_usec/1.0e6)-
1921+
(starttime.tv_sec+starttime.tv_usec/1.0e6) );
1922+
}
1923+
19071924
/* ==================================================================== */
19081925
/* Now process the data, applying to the working imageObj. */
19091926
/* ==================================================================== */

Diff for: mapraster.c

+40-18
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ extern parseResultObj yypresult; /* result of parsing, true/false */
6060
/* msGetClass_String() */
6161
/************************************************************************/
6262

63-
static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixel_value )
63+
static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixel_value, int firstClassToTry )
6464

6565
{
6666
int i;
@@ -80,9 +80,18 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
8080
/* Setup values list for expressions. */
8181
/* -------------------------------------------------------------------- */
8282
numitems = 4;
83-
sprintf( red_value, "%d", color->red );
84-
sprintf( green_value, "%d", color->green );
85-
sprintf( blue_value, "%d", color->blue );
83+
if( color->red == -1 && color->green == -1 && color->blue == -1 )
84+
{
85+
strcpy(red_value, "-1");
86+
strcpy(green_value, "-1");
87+
strcpy(blue_value, "-1");
88+
}
89+
else
90+
{
91+
sprintf( red_value, "%d", color->red );
92+
sprintf( green_value, "%d", color->green );
93+
sprintf( blue_value, "%d", color->blue );
94+
}
8695

8796
item_values[0] = (char *)pixel_value;
8897
item_values[1] = red_value;
@@ -92,18 +101,24 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
92101
/* -------------------------------------------------------------------- */
93102
/* Loop over classes till we find a match. */
94103
/* -------------------------------------------------------------------- */
95-
for(i=0; i<layer->numclasses; i++) {
104+
for(i= (firstClassToTry < 0 ) ? 0 : -1; i<layer->numclasses; i++) {
105+
106+
int idx = i;
107+
if( i < 0 )
108+
idx = firstClassToTry;
109+
else if( i == firstClassToTry )
110+
continue;
96111

97112
/* check for correct classgroup, if set */
98-
if ( layer->class[i]->group && layer->classgroup &&
99-
strcasecmp(layer->class[i]->group, layer->classgroup) != 0 )
113+
if ( layer->class[idx]->group && layer->classgroup &&
114+
strcasecmp(layer->class[idx]->group, layer->classgroup) != 0 )
100115
continue;
101116

102117
/* Empty expression - always matches */
103-
if (layer->class[i]->expression.string == NULL)
118+
if (layer->class[idx]->expression.string == NULL)
104119
return(i);
105120

106-
switch(layer->class[i]->expression.type) {
121+
switch(layer->class[idx]->expression.type) {
107122

108123
/* -------------------------------------------------------------------- */
109124
/* Simple string match */
@@ -114,22 +129,22 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
114129
while( *tmpstr1 == ' ' )
115130
tmpstr1++;
116131

117-
if(strcmp(layer->class[i]->expression.string, tmpstr1) == 0) return(i); /* matched */
132+
if(strcmp(layer->class[idx]->expression.string, tmpstr1) == 0) return(idx); /* matched */
118133
break;
119134

120135
/* -------------------------------------------------------------------- */
121136
/* Regular expression. Rarely used for raster. */
122137
/* -------------------------------------------------------------------- */
123138
case(MS_REGEX):
124-
if(!layer->class[i]->expression.compiled) {
125-
if(ms_regcomp(&(layer->class[i]->expression.regex), layer->class[i]->expression.string, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { /* compile the expression */
139+
if(!layer->class[idx]->expression.compiled) {
140+
if(ms_regcomp(&(layer->class[idx]->expression.regex), layer->class[idx]->expression.string, MS_REG_EXTENDED|MS_REG_NOSUB) != 0) { /* compile the expression */
126141
msSetError(MS_REGEXERR, "Invalid regular expression.", "msGetClass()");
127142
return(-1);
128143
}
129-
layer->class[i]->expression.compiled = MS_TRUE;
144+
layer->class[idx]->expression.compiled = MS_TRUE;
130145
}
131146

132-
if(ms_regexec(&(layer->class[i]->expression.regex), pixel_value, 0, NULL, 0) == 0) return(i); /* got a match */
147+
if(ms_regexec(&(layer->class[idx]->expression.regex), pixel_value, 0, NULL, 0) == 0) return(idx); /* got a match */
133148
break;
134149

135150
/* -------------------------------------------------------------------- */
@@ -139,7 +154,7 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
139154
int status;
140155
parseObj p;
141156
shapeObj dummy_shape;
142-
expressionObj *expression = &(layer->class[i]->expression);
157+
expressionObj *expression = &(layer->class[idx]->expression);
143158

144159
dummy_shape.numvalues = numitems;
145160
dummy_shape.values = item_values;
@@ -160,7 +175,7 @@ static int msGetClass_String( layerObj *layer, colorObj *color, const char *pixe
160175
}
161176

162177
if( p.result.intval )
163-
return i;
178+
return idx;
164179
break;
165180
}
166181
}
@@ -179,7 +194,7 @@ int msGetClass(layerObj *layer, colorObj *color, int colormap_index)
179194

180195
snprintf( pixel_value, sizeof(pixel_value), "%d", colormap_index );
181196

182-
return msGetClass_String( layer, color, pixel_value );
197+
return msGetClass_String( layer, color, pixel_value, -1 );
183198
}
184199

185200
/************************************************************************/
@@ -190,6 +205,13 @@ int msGetClass(layerObj *layer, colorObj *color, int colormap_index)
190205
/************************************************************************/
191206

192207
int msGetClass_FloatRGB(layerObj *layer, float fValue, int red, int green, int blue )
208+
{
209+
return msGetClass_FloatRGB_WithFirstClassToTry(
210+
layer, fValue, red, green, blue, -1);
211+
}
212+
213+
214+
int msGetClass_FloatRGB_WithFirstClassToTry(layerObj *layer, float fValue, int red, int green, int blue, int firstClassToTry )
193215
{
194216
char pixel_value[100];
195217
colorObj color;
@@ -200,7 +222,7 @@ int msGetClass_FloatRGB(layerObj *layer, float fValue, int red, int green, int b
200222

201223
snprintf( pixel_value, sizeof(pixel_value), "%18g", fValue );
202224

203-
return msGetClass_String( layer, &color, pixel_value );
225+
return msGetClass_String( layer, &color, pixel_value, firstClassToTry );
204226
}
205227

206228
#if defined(USE_GDAL)

Diff for: mapserver.h

+1
Original file line numberDiff line numberDiff line change
@@ -2589,6 +2589,7 @@ void msPopulateTextSymbolForLabelAndString(textSymbolObj *ts, labelObj *l, char
25892589
MS_DLL_EXPORT int msGetClass(layerObj *layer, colorObj *color, int colormap_index);
25902590
MS_DLL_EXPORT int msGetClass_FloatRGB(layerObj *layer, float fValue,
25912591
int red, int green, int blue );
2592+
int msGetClass_FloatRGB_WithFirstClassToTry(layerObj *layer, float fValue, int red, int green, int blue, int firstClassToTry );
25922593

25932594
/* in mapdrawgdal.c */
25942595
MS_DLL_EXPORT int msDrawRasterLayerGDAL(mapObj *map, layerObj *layer, imageObj *image, rasterBufferObj *rb, void *hDSVoid );

0 commit comments

Comments
 (0)