Re: stack usage in toast_insert_or_update() - Mailing list pgsql-hackers

From Pavan Deolasee
Subject Re: stack usage in toast_insert_or_update()
Date
Msg-id 2e78013d0701310319o2d9d0bbdne2b7396732174a5b@mail.gmail.com
Whole thread Raw
In response to Re: stack usage in toast_insert_or_update()  (Tom Lane <tgl@sss.pgh.pa.us>)
Responses Re: stack usage in toast_insert_or_update()
Re: stack usage in toast_insert_or_update()
List pgsql-hackers

On 1/31/07, Tom Lane <tgl@sss.pgh.pa.us> wrote:
"Pavan Deolasee" <pavan.deolasee@gmail.com> writes:
> Btw, I noticed that the toast_insert_or_update() is re-entrant.
> toast_save_datum() calls simple_heap_insert() which somewhere down the
> line calls toast_insert_or_update() again.

The toast code takes pains to ensure that the tuples it creates won't be
subject to re-toasting.  Else it'd be an infinite recursion.

I think I found it. The toast_insert_or_update() function gets into an unnecessary
recursion because of alignment issues. It thus toasts already toasted data. This
IMHO might be causing unnecessary overheads for each toast operation.

The default value of TOAST_TUPLE_THRESHOLD is 2034 (assuming 8K block size)

TOAST_MAX_CHUNK_SIZE is defined as below:

#define TOAST_MAX_CHUNK_SIZE    (TOAST_TUPLE_THRESHOLD -            \
             MAXALIGN(                                               \
                MAXALIGN(offsetof(HeapTupleHeaderData, t_bits)) +   \
                sizeof(Oid) +                                       \
                sizeof(int32) +                                     \
                VARHDRSZ))

So the default value of TOAST_MAX_CHUNK_SIZE is set to 1994.

When toast_insert_or_update() returns a tuple for the first chunk, t_len
is set to 2034 (TOAST_MAX_CHUNK_SIZE + tuple header + chunk_id
+ chunk_seqno + VARHDRSZ)

In heap_insert(), we MAXALIGN(tup->t_len) before comparing it with
TOAST_TUPLE_THRESHOLD to decide whether to invoke TOAST or not.
In this corner case, MAXALIGN(2034) = 2036 > TOAST_TUPLE_THRESHOLD
and so TOAST is invoked again.

Fortunately, we don't get into infinite recursion because reltoastrelid is set to
InvalidOid for toast tables and hence TOASTing is not invoked in the second
call.

Attached is a patch which would print the recursion depth for
toast_insert_or_update() before PANICing the server to help us
examine the core.

Let me know if this sounds like an issue and  I can work out a patch.

Thanks,
Pavan

--

EnterpriseDB     http://www.enterprisedb.com

pgsql-hackers by date:

Previous
From: Heikki Linnakangas
Date:
Subject: Re: crash on 8.2 and cvshead - failed to add item to the
Next
From: "Pavan Deolasee"
Date:
Subject: Re: stack usage in toast_insert_or_update()