1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-12 21:01:52 +03:00

Avoid some other O(N^2) hazards in list manipulation.

In the same spirit as 6301c3ada, fix some more places where we were
using list_delete_first() in a loop and thereby risking O(N^2)
behavior.  It's not clear that the lists manipulated in these spots
can get long enough to be really problematic ... but it's not clear
that they can't, either, and the fixes are simple enough.

As before, back-patch to v13.

Discussion: https://postgr.es/m/CD2F0E7F-9822-45EC-A411-AE56F14DEA9F@amazon.com
This commit is contained in:
Tom Lane
2021-11-01 16:24:39 -04:00
parent 40c516bba8
commit e9d9ba2a4d
3 changed files with 27 additions and 25 deletions

View File

@ -2584,8 +2584,9 @@ agg_refill_hash_table(AggState *aggstate)
if (aggstate->hash_batches == NIL)
return false;
batch = linitial(aggstate->hash_batches);
aggstate->hash_batches = list_delete_first(aggstate->hash_batches);
/* hash_batches is a stack, with the top item at the end of the list */
batch = llast(aggstate->hash_batches);
aggstate->hash_batches = list_delete_last(aggstate->hash_batches);
hash_agg_set_limits(aggstate->hashentrysize, batch->input_card,
batch->used_bits, &aggstate->hash_mem_limit,
@ -3098,7 +3099,7 @@ hashagg_spill_finish(AggState *aggstate, HashAggSpill *spill, int setno)
new_batch = hashagg_batch_new(tape, setno,
spill->ntuples[i], cardinality,
used_bits);
aggstate->hash_batches = lcons(new_batch, aggstate->hash_batches);
aggstate->hash_batches = lappend(aggstate->hash_batches, new_batch);
aggstate->hash_batches_used++;
}
@ -3113,8 +3114,6 @@ hashagg_spill_finish(AggState *aggstate, HashAggSpill *spill, int setno)
static void
hashagg_reset_spill_state(AggState *aggstate)
{
ListCell *lc;
/* free spills from initial pass */
if (aggstate->hash_spills != NULL)
{
@ -3132,13 +3131,7 @@ hashagg_reset_spill_state(AggState *aggstate)
}
/* free batches */
foreach(lc, aggstate->hash_batches)
{
HashAggBatch *batch = (HashAggBatch *) lfirst(lc);
pfree(batch);
}
list_free(aggstate->hash_batches);
list_free_deep(aggstate->hash_batches);
aggstate->hash_batches = NIL;
/* close tape set */