f970f8e2fd81d08901048b2070054dd71ed7f1f1 angie Tue Apr 9 11:47:57 2013 -0700 Use localmem for annoRow storage, instead of many independent malloc & free calls. refs #6152 diff --git src/lib/annoGrateWig.c src/lib/annoGrateWig.c index f0ab749..bafc248 100644 --- src/lib/annoGrateWig.c +++ src/lib/annoGrateWig.c @@ -1,87 +1,108 @@ /* annoGrateWig -- subclass of annoGrator for bigWig or wiggle data */ #include "annoGrateWig.h" #include "annoStreamBigWig.h" +struct annoGrateWig +{ + struct annoGrator grator; // external annoGrator interface + struct annoGrator *mySource; // internal annoGrator of wigDb rows + struct lm *lm; // localmem for rows from mySource + int lmRowCount; // counter for periodic cleanup +}; + static void tidyUp(const struct annoRow *rowIn, struct annoRow **pOutList, - uint primaryStart, uint primaryEnd) + uint primaryStart, uint primaryEnd, struct lm *callerLm) /* This takes a wiggle chunk coming from a .wig/database row and makes it into * zero or more tidy little NAN-less annoRows. Trim rowIn to the bounds of * primary, trim NANs from beginning and break into multiple rows where there * are NANs in the middle. If the rowIn is contiguous with the row at the * head of outList, expand that row to include rowIn's data. */ { uint start = max(rowIn->start, primaryStart); uint end = min(rowIn->end, primaryEnd); float *vector = rowIn->data; while (end > start) { uint offset = start - rowIn->start; if (vector[offset] == NAN) start++; else { // If there is a NAN before end, that's the end of this row: uint thisEnd = start; while (thisEnd < end && vector[thisEnd - rowIn->start] != NAN) thisEnd++; struct annoRow *headRow = *pOutList; if (headRow == NULL || rowIn->start > headRow->end) { // allocate a new row struct annoRow *rowOut = annoRowWigNew(rowIn->chrom, start, thisEnd, FALSE, - vector + offset); + vector + offset, callerLm); slAddHead(pOutList, rowOut); } else { // glom new data onto headRow assert(thisEnd > headRow->end); uint oldEnd = headRow->end; uint oldLen = oldEnd - headRow->start; uint newLen = thisEnd - headRow->start; - headRow->data = needMoreMem(headRow->data, oldLen*sizeof(vector[0]), + headRow->data = lmAllocMoreMem(callerLm, headRow->data, oldLen*sizeof(vector[0]), newLen*sizeof(vector[0])); headRow->end = thisEnd; float *newData = (float *)rowIn->data + (oldEnd - rowIn->start); float *newSpace = (float *)headRow->data + oldLen; CopyArray(newData, newSpace, (thisEnd - oldEnd)); } start = thisEnd; } } } -static struct annoRow *agwIntegrate(struct annoGrator *self, struct annoRow *primaryRow, - boolean *retRJFilterFailed) +static struct annoRow *agwIntegrate(struct annoGrator *gSelf, struct annoRow *primaryRow, + boolean *retRJFilterFailed, struct lm *callerLm) /* Return wig annoRows that overlap primaryRow position, with NANs weeded out. */ { -struct annoRow *rowsIn = annoGratorIntegrate(self, primaryRow, retRJFilterFailed); +struct annoGrateWig *self = (struct annoGrateWig *)gSelf; +// Cleanup internal lm every so often: +if (self->lmRowCount >= 4096) + { + lmCleanup(&(self->lm)); + self->lmRowCount = 0; + } +if (self->lm == NULL) + self->lm = lmInit(0); +struct annoRow *rowsIn = annoGratorIntegrate(self->mySource, primaryRow, retRJFilterFailed, + self->lm); +self->lmRowCount += slCount(rowsIn); if (retRJFilterFailed && *retRJFilterFailed) return NULL; struct annoRow *rowIn, *rowOutList = NULL;; for (rowIn = rowsIn; rowIn != NULL; rowIn = rowIn->next) - tidyUp(rowIn, &rowOutList, primaryRow->start, primaryRow->end); + tidyUp(rowIn, &rowOutList, primaryRow->start, primaryRow->end, callerLm); slReverse(&rowOutList); -annoRowFreeList(&rowsIn, self->mySource); return rowOutList; } struct annoGrator *annoGrateWigNew(struct annoStreamer *wigSource) /* Create an annoGrator subclass for source with rowType == arWig. */ { if (wigSource->rowType != arWig) errAbort("annoGrateWigNew: expected source->rowType arWig (%d), got %d", arWig, wigSource->rowType); -struct annoGrator *self = annoGratorNew(wigSource); -self->streamer.rowType = arWig; -self->integrate = agwIntegrate; -return self; +struct annoGrateWig *self; +AllocVar(self); +struct annoGrator *gSelf = (struct annoGrator *)self; +annoGratorInit(gSelf, wigSource); +gSelf->integrate = agwIntegrate; +self->mySource = annoGratorNew(wigSource); +return gSelf; } struct annoGrator *annoGrateBigWigNew(char *fileOrUrl) /* Create an annoGrator subclass for bigWig file or URL. */ { struct annoStreamer *bigWigSource = annoStreamBigWigNew(fileOrUrl); return annoGrateWigNew(bigWigSource); }