*** ./src/backend/tsearch/regis.c.orig 2010-07-14 11:47:33.068437888 +0200 --- ./src/backend/tsearch/regis.c 2010-07-14 14:32:47.157437908 +0200 *************** *** 16,27 **** --- 16,34 ---- #include "tsearch/dicts/regis.h" #include "tsearch/ts_locale.h" + #include "tsearch/dicts/spell.h" #define RS_IN_ONEOF 1 #define RS_IN_ONEOF_IN 2 #define RS_IN_NONEOF 3 #define RS_IN_WAIT 4 + extern AllocOnlyBlocksData aob; + + #define aoalloc(sz) ao_alloc(&aob, (sz), false) + #define aoalloc0(sz) ao_alloc(&aob, (sz), true) + #define aostrdup(str) ao_strdup(&aob, (str)) + /* * Test whether a regex is of the subset supported here. * Keep this in sync with RS_compile! *************** *** 74,80 **** { RegisNode *ptr; ! ptr = (RegisNode *) palloc0(RNHDRSZ + len + 1); if (prev) prev->next = ptr; return ptr; --- 81,87 ---- { RegisNode *ptr; ! ptr = (RegisNode *) aoalloc0(RNHDRSZ + len + 1); if (prev) prev->next = ptr; return ptr; *** ./src/backend/tsearch/spell.c.orig 2010-01-02 17:57:53.000000000 +0100 --- ./src/backend/tsearch/spell.c 2010-07-14 14:46:06.513562368 +0200 *************** *** 28,36 **** --- 28,97 ---- */ static MemoryContext tmpCtx = NULL; + #define ALLOC_ONLY_MAXSIZE 512 + + AllocOnlyBlocksData aob; + AllocOnlyBlocksData tmpaob; + #define tmpalloc(sz) MemoryContextAlloc(tmpCtx, (sz)) #define tmpalloc0(sz) MemoryContextAllocZero(tmpCtx, (sz)) + #define aoalloc(sz) ao_alloc(&aob, (sz), false) + #define aoalloc0(sz) ao_alloc(&aob, (sz), true) + #define aostrdup(str) ao_strdup(&aob, (str)) + + #define aotmpalloc(sz) ao_alloc(&tmpaob, (sz), false) + #define aotpmalloc0(sz) ao_alloc(&tmpaob, (sz), true) + #define aotmpstrdup(str) ao_strdup(&tmpaob, (str)) + + /* + * Ispell dictionary uses a thousands small blocks and because + * doesn't release these blocks, we can save lot of memory via + * sharing mcxt blocks. + */ + char * + ao_alloc(AllocOnlyBlocksData *aob, Size size, bool fillzero) + { + char *ptr; + + size = MAXALIGN(size); + + /* + * for "larger" blocks use a mcxt allocator. It is simple + * mechanism to ensure a well fragmentation of alloc only + * blocks. + */ + if (size > ALLOC_ONLY_MAXSIZE) + return fillzero ? MemoryContextAllocZero(aob->ctx, size) : MemoryContextAlloc(aob->ctx, size); + + if (size > aob->freesize) + { + aob->freeptr = MemoryContextAlloc(aob->ctx, ALLOCSET_DEFAULT_INITSIZE); + aob->freesize = ALLOCSET_DEFAULT_INITSIZE; + } + + ptr = aob->freeptr; + aob->freeptr += size; + aob->freesize -= size; + + if (fillzero) + memset(ptr, 0, size); + + return ptr; + } + + char * + ao_strdup(AllocOnlyBlocksData *aob, const char *string) + { + char *nstr; + Size len = strlen(string) + 1; + + nstr = (char *) ao_alloc(aob, len, false); + memcpy(nstr, string, len);; + + return nstr; + } + static void checkTmpCtx(void) { *************** *** 48,53 **** --- 109,120 ---- } else tmpCtx = CurrentMemoryContext->firstchild; + + tmpaob.ctx = tmpCtx; + tmpaob.freesize = 0; + + aob.ctx = CurrentMemoryContext; + aob.freesize = 0; } static char * *************** *** 179,185 **** Conf->Spell = (SPELL **) tmpalloc(Conf->mspell * sizeof(SPELL *)); } } ! Conf->Spell[Conf->nspell] = (SPELL *) tmpalloc(SPELLHDRSZ + strlen(word) + 1); strcpy(Conf->Spell[Conf->nspell]->word, word); strncpy(Conf->Spell[Conf->nspell]->p.flag, flag, MAXFLAGLEN); Conf->nspell++; --- 246,253 ---- Conf->Spell = (SPELL **) tmpalloc(Conf->mspell * sizeof(SPELL *)); } } ! ! Conf->Spell[Conf->nspell] = (SPELL *) aotmpalloc(SPELLHDRSZ + strlen(word) + 1); strcpy(Conf->Spell[Conf->nspell]->word, word); strncpy(Conf->Spell[Conf->nspell]->p.flag, flag, MAXFLAGLEN); Conf->nspell++; *************** *** 344,357 **** Affix->issimple = 0; Affix->isregis = 0; ! tmask = (char *) tmpalloc(strlen(mask) + 3); if (type == FF_SUFFIX) sprintf(tmask, "%s$", mask); else sprintf(tmask, "^%s", mask); masklen = strlen(tmask); ! wmask = (pg_wchar *) tmpalloc((masklen + 1) * sizeof(pg_wchar)); wmasklen = pg_mb2wchar_with_len(tmask, wmask, masklen); err = pg_regcomp(&(Affix->reg.regex), wmask, wmasklen, REG_ADVANCED | REG_NOSUB); --- 412,425 ---- Affix->issimple = 0; Affix->isregis = 0; ! tmask = (char *) aotmpalloc(strlen(mask) + 3); if (type == FF_SUFFIX) sprintf(tmask, "%s$", mask); else sprintf(tmask, "^%s", mask); masklen = strlen(tmask); ! wmask = (pg_wchar *) aotmpalloc((masklen + 1) * sizeof(pg_wchar)); wmasklen = pg_mb2wchar_with_len(tmask, wmask, masklen); err = pg_regcomp(&(Affix->reg.regex), wmask, wmasklen, REG_ADVANCED | REG_NOSUB); *************** *** 375,383 **** Affix->flag = flag; Affix->type = type; ! Affix->find = (find && *find) ? pstrdup(find) : VoidString; if ((Affix->replen = strlen(repl)) > 0) ! Affix->repl = pstrdup(repl); else Affix->repl = VoidString; Conf->naffixes++; --- 443,451 ---- Affix->flag = flag; Affix->type = type; ! Affix->find = (find && *find) ? aostrdup(find) : VoidString; if ((Affix->replen = strlen(repl)) > 0) ! Affix->repl = aostrdup(repl); else Affix->repl = VoidString; Conf->naffixes++; *************** *** 833,839 **** } ptr = Conf->AffixData + Conf->nAffixData; ! *ptr = palloc(strlen(Conf->AffixData[a1]) + strlen(Conf->AffixData[a2]) + 1 /* space */ + 1 /* \0 */ ); sprintf(*ptr, "%s %s", Conf->AffixData[a1], Conf->AffixData[a2]); ptr++; --- 901,907 ---- } ptr = Conf->AffixData + Conf->nAffixData; ! *ptr = aoalloc(strlen(Conf->AffixData[a1]) + strlen(Conf->AffixData[a2]) + 1 /* space */ + 1 /* \0 */ ); sprintf(*ptr, "%s %s", Conf->AffixData[a1], Conf->AffixData[a2]); ptr++; *************** *** 878,884 **** if (!nchar) return NULL; ! rs = (SPNode *) palloc0(SPNHDRSZ + nchar * sizeof(SPNodeData)); rs->length = nchar; data = rs->data; --- 946,952 ---- if (!nchar) return NULL; ! rs = (SPNode *) aoalloc0(SPNHDRSZ + nchar * sizeof(SPNodeData)); rs->length = nchar; data = rs->data; *************** *** 965,971 **** * dictionary. Replace textual flag-field of Conf->Spell entries with * indexes into Conf->AffixData array. */ ! Conf->AffixData = (char **) palloc0(naffix * sizeof(char *)); curaffix = -1; for (i = 0; i < Conf->nspell; i++) --- 1033,1039 ---- * dictionary. Replace textual flag-field of Conf->Spell entries with * indexes into Conf->AffixData array. */ ! Conf->AffixData = (char **) aoalloc0(naffix * sizeof(char *)); curaffix = -1; for (i = 0; i < Conf->nspell; i++) *************** *** 974,980 **** { curaffix++; Assert(curaffix < naffix); ! Conf->AffixData[curaffix] = pstrdup(Conf->Spell[i]->p.flag); } Conf->Spell[i]->p.d.affix = curaffix; --- 1042,1048 ---- { curaffix++; Assert(curaffix < naffix); ! Conf->AffixData[curaffix] = aostrdup(Conf->Spell[i]->p.flag); } Conf->Spell[i]->p.d.affix = curaffix; *************** *** 1014,1020 **** aff = (AFFIX **) tmpalloc(sizeof(AFFIX *) * (high - low + 1)); naff = 0; ! rs = (AffixNode *) palloc0(ANHRDSZ + nchar * sizeof(AffixNodeData)); rs->length = nchar; data = rs->data; --- 1082,1088 ---- aff = (AFFIX **) tmpalloc(sizeof(AFFIX *) * (high - low + 1)); naff = 0; ! rs = (AffixNode *) aoalloc0(ANHRDSZ + nchar * sizeof(AffixNodeData)); rs->length = nchar; data = rs->data; *************** *** 1030,1036 **** if (naff) { data->naff = naff; ! data->aff = (AFFIX **) palloc(sizeof(AFFIX *) * naff); memcpy(data->aff, aff, sizeof(AFFIX *) * naff); naff = 0; } --- 1098,1104 ---- if (naff) { data->naff = naff; ! data->aff = (AFFIX **) aoalloc(sizeof(AFFIX *) * naff); memcpy(data->aff, aff, sizeof(AFFIX *) * naff); naff = 0; } *************** *** 1050,1056 **** if (naff) { data->naff = naff; ! data->aff = (AFFIX **) palloc(sizeof(AFFIX *) * naff); memcpy(data->aff, aff, sizeof(AFFIX *) * naff); naff = 0; } --- 1118,1124 ---- if (naff) { data->naff = naff; ! data->aff = (AFFIX **) aoalloc(sizeof(AFFIX *) * naff); memcpy(data->aff, aff, sizeof(AFFIX *) * naff); naff = 0; } *************** *** 1067,1073 **** cnt = 0; int start = (issuffix) ? startsuffix : 0; int end = (issuffix) ? Conf->naffixes : startsuffix; ! AffixNode *Affix = (AffixNode *) palloc0(ANHRDSZ + sizeof(AffixNodeData)); Affix->length = 1; Affix->isvoid = 1; --- 1135,1141 ---- cnt = 0; int start = (issuffix) ? startsuffix : 0; int end = (issuffix) ? Conf->naffixes : startsuffix; ! AffixNode *Affix = (AffixNode *) aoalloc0(ANHRDSZ + sizeof(AffixNodeData)); Affix->length = 1; Affix->isvoid = 1; *************** *** 1091,1097 **** if (cnt == 0) return; ! Affix->data->aff = (AFFIX **) palloc(sizeof(AFFIX *) * cnt); Affix->data->naff = (uint32) cnt; cnt = 0; --- 1159,1165 ---- if (cnt == 0) return; ! Affix->data->aff = (AFFIX **) aoalloc(sizeof(AFFIX *) * cnt); Affix->data->naff = (uint32) cnt; cnt = 0; *************** *** 1658,1664 **** addNorm(TSLexeme **lres, TSLexeme **lcur, char *word, int flags, uint16 NVariant) { if (*lres == NULL) ! *lcur = *lres = (TSLexeme *) palloc(MAX_NORM * sizeof(TSLexeme)); if (*lcur - *lres < MAX_NORM - 1) { --- 1726,1732 ---- addNorm(TSLexeme **lres, TSLexeme **lcur, char *word, int flags, uint16 NVariant) { if (*lres == NULL) ! *lcur = *lres = (TSLexeme *) aoalloc(MAX_NORM * sizeof(TSLexeme)); if (*lcur - *lres < MAX_NORM - 1) { *** ./src/include/tsearch/dicts/spell.h.orig 2010-04-02 17:21:20.000000000 +0200 --- ./src/include/tsearch/dicts/spell.h 2010-07-14 14:23:42.210440053 +0200 *************** *** 160,169 **** --- 160,180 ---- bool usecompound; } IspellDict; + typedef struct + { + MemoryContext ctx; + Size freesize; + char *freeptr; + } AllocOnlyBlocksData; + extern TSLexeme *NINormalizeWord(IspellDict *Conf, char *word); extern void NIImportAffixes(IspellDict *Conf, const char *filename); extern void NIImportDictionary(IspellDict *Conf, const char *filename); extern void NISortDictionary(IspellDict *Conf); extern void NISortAffixes(IspellDict *Conf); + extern char *ao_alloc(AllocOnlyBlocksData *aob, Size size, bool fillzero); + extern char *ao_strdup(AllocOnlyBlocksData *aob, const char *string); + + #endif