On Sun, Jan 19, 2025 at 9:12 PM Yura Sokolov <y.sokolov@postgrespro.ru> wrote:
>
> 20.01.2025 07:36, Tom Lane пишет:
...
> > This has been discussed before, and we've felt that it wasn't worth
> > the additional code duplication. I would not favor approaching this
> > with the mindset of lets-copy-and-paste-all-the-code.
> >
> > However: it might be interesting to think about having just two
> > underlying implementations, one for 32-bit datums and one for 64-bits,
> > with the existing APIs becoming macros-with-casts wrappers around the
> > appropriate one of those. That line of attack might lead to
> > physically less code not more. The devil's in the details though.
>
> There's masterpiece typesafe std-C compliant macros+functions
> implementation of vector:
>
> https://github.com/rxi/vec/
>
> It wraps any struct with "T *data; int length; int capacity" fields, and
> uses `sizeof(*(v)->data)` to instruct wrapped allocation/move functions.
>
> Although it could not be directly adapted to List*, and it is less
> sophisticated considering "mutation during iteration", it could be
> really useful in many places, where List* used not as a Node, but just
> as dynamic array.
+1 to adopting something like this ^ for std::vector-like resizable
arrays of fixed-size values.
The overhead of pg_list is not just the cost of an extra pointer
dereference (because you have to store the List as a T* array, rather
than a T array), but also the palloc() overhead, since every T* must
point to a T, and so that T must live somewhere on the heap.
I sometimes see palloc() showing up in perf reports, so the allocation
cost of T* vs. T seems non-zero to me.
In one case, I want to store a 4x 4-byte struct in some sort of list /
expandable array. From a human-readability point of view, it's awkward
to split the struct into 4x IntLists; from a CPU point of view, it's
awkward to take up an 8-byte pointer to point to a 16-byte struct,
allocated on the heap.
James