[Mapserver-dev] Optimizing msAddLine()

David Turover dturover at student.santarosa.edu
Wed Jan 8 14:08:58 EST 2003


On Mon, 6 Jan 2003, Daniel Morissette wrote:
> Steve Lime wrote:
> > 
> > Thanks David, lemme (and others?) look through the code and test it a
> > bit. Certainly looks
> > promising though. Wonder how much affect it has in web use...
> > 
> 
> I think the basic idea is great (better than reallocating one item
> at a time), but I'm worried a bit by the overhead in memory usage
> involved in general use of the current solution, especially for things
> like the labelcache that stores shapes for each label.
[snip]
> Anyway, what I wanted to propose is to start with a smaller buffer and
> double the buffer size everytime we realloc, e.g. start with a buffer of
> 8 lineObj, then realloc to 16, 32, 64, 128, ... ...
[snip]

How does this look?

void msArrayResizeIfFull(void ** arrayPtr, int numItems, int itemSize){
        const static int maxArraySegment = 256;
        void * newArray;

        if(arrayPtr == NULL) return;

        /* Set newArray equal to the original array so
        ** if newArray changes we know that malloc was called on it,
        ** and that newArray == NULL means malloc failed. */
        newArray = *arrayPtr;

        if(numItems < maxArraySegment){
                switch(numItems){
                case 0: /* malloc an initial array */
                        newArray = calloc(8, itemSize);
                        break;
                case 8:         /* Fall through */
                case 16:        /* Fall through */
                case 32:        /* Fall through */
                case 64:        /* Fall through */
                case 128:
                        newArray = calloc(numItems * 2, itemSize);
                        memcpy(newArray, *arrayPtr, numItems * itemSize);
                        break;
                default: break;
                }
        } else if(numItems % maxArraySegment == 0){
                newArray = calloc(numItems + maxArraySegment,itemSize);
                memcpy(newArray, *arrayPtr, numItems * itemSize);
        }

        if(newArray != *arrayPtr){
                if(newArray == NULL)
                        msSetError(MS_MEMERR, NULL, "msArrayResizeIfFull()");
                else{
                        msFree(*arrayPtr);
                        *arrayPtr = newArray;
                }
        }

        return;
}


And msAddLine() becomes:

int msAddLine(shapeObj *p, lineObj *new_line){
        lineObj *extended_line;

        msArrayResizeIfFull((void **)&p->line, p->numlines, sizeof(lineObj));

        /* Update the polygon information */
        extended_line = &p->line[p->numlines];

        /* Copy the points to the line array */
        extended_line->numpoints = new_line->numpoints;
        if((extended_line->point = (pointObj *)malloc(new_line->numpoints
                 * sizeof(pointObj))) == NULL) {
                msSetError(MS_MEMERR, NULL, "msAddLine()");
                return(-1);
        }
        memcpy(extended_line->point, new_line->point, new_line->numpoints 
* sizeof(pointObj));
        p->numlines++;

        return(0);
}


This hasn't been well tested (it runs here, but I haven't tried to hit 
every branch to see what happens).

BTW: I glanced at maplabel.c and it appears the labelcache is already
expanding by increments of 10, so that shouldn't be a problem.





More information about the mapserver-dev mailing list