On Mon, 1 Jul 2024 at 10:56, David Rowley <dgrowle...@gmail.com> wrote: > > Currently, TupleDescData contains the descriptor's attributes in a > variable length array of FormData_pg_attribute allocated within the > same allocation as the TupleDescData. According to my IDE, > sizeof(FormData_pg_attribute) == 104 bytes. It's that large mainly due > to attname being 64 bytes. The TupleDescData.attrs[] array could end > up quite large on tables with many columns and that could result in > poor CPU cache hit ratios when deforming tuples. > > Instead, we could make TupleDescData contain an out-of-line pointer to > the array of FormData_pg_attribute and have a much more compact > inlined array of some other struct that much more densely contains the > fields required for tuple deformation. attname and many of the other > fields are not required to deform a tuple.
+1 > I've attached a patch series which does this. > > 0001: Just fixes up some missing usages of TupleDescAttr(). (mostly > missed by me, apparently :-( ) > 0002: Adjusts the TupleDescData.attrs array to make it out of line. I > wanted to make sure nothing weird happened by doing this before doing > the bulk of the other changes to add the new struct. > 0003: Adds a very compact 8-byte struct named TupleDescDeformAttr, > which can be used for tuple deformation. 8 columns fits on a 64-byte > cacheline rather than 13 cachelines. Cool, that's similar to, but even better than, my patch from 2021 over at [0]. One thing I'm slightly concerned about is that this allocates another 8 bytes for each attribute in the tuple descriptor. While that's not a lot when compared with the ->attrs array, it's still quite a lot when we might not care at all about this data; e.g. in temporary tuple descriptors during execution, in intermediate planner nodes. Did you test for performance gains (or losses) with an out-of-line TupleDescDeformAttr array? One benefit from this would be that we could reuse the deform array for suffix truncated TupleDescs, reuse of which currently would require temporarily updating TupleDesc->natts with a smaller value; but with out-of-line ->attrs and ->deform_attrs, we could reuse these arrays between TupleDescs if one is shorter than the other, but has otherwise fully matching attributes. I know that btree split code would benefit from this, as it wouldn't have to construct a full new TupleDesc when it creates a suffix-truncated tuple during page splits. > 0004: Adjusts the attalign to change it from char to uint8. See below. > > The 0004 patch changes the TupleDescDeformAttr.attalign to a uint8 > rather than a char containing 'c', 's', 'i' or 'd'. This allows much > more simple code in the att_align_nominal() macro. What's in master is > quite a complex expression to evaluate every time we deform a column > as it much translate: 'c' -> 1, 's' -> 2, 'i' -> 4, 'd' -> 8. If we > just store that numeric value in the struct that macro can become a > simple TYPEALIGN() so the operation becomes simple bit masking rather > than a poorly branch predictable series of compare and jump. +1, that's something I'd missed in my patches, and is probably the largest contributor to the speedup. > I'll stick this in the July CF. It would be good to get some feedback > on the idea and feedback on whether more work on this is worthwhile. Do you plan to remove the ->attcacheoff catalog field from the FormData_pg_attribute, now that (with your patch) it isn't used anymore as a placeholder field for fast (de)forming of tuples? Kind regards, Matthias van de Meent [0] https://www.postgresql.org/message-id/CAEze2Wh8-metSryZX_Ubj-uv6kb%2B2YnzHAejmEdubjhmGusBAg%40mail.gmail.com