Why does bootstrap and later initdb stages happen via client?
Hi,
While hacking on AIO I wanted to build the windows portion from linux. That
works surprisingly well with cross-building using --host=x86_64-w64-mingw32 .
What didn't work as well was running things under wine. It turns out that the
server itself works ok, but that initdb hangs because of a bug in wine ([1]https://bugs.winehq.org/show_bug.cgi?id=51719),
leading to the bootstrap process hanging while trying to read more input.
Which made me wonder: What is really the point of doing so much setup as part
of initdb? Of course a wine bug isn't a reason to change anything, but I see
other reasons it might be worth thinking about moving more of initdb's logic
into the backend.
There of course is historical raisins for things happening in initdb - the
setup logic didn't use to be C. But now that it is C, it seems a bit absurd to
read bootstrap data in initdb, write the data to a pipe, and then read it
again in the backend. It for sure doesn't make things faster.
If more of initdb happened in the backend, it seems plausible that we could
avoid the restart of the server between bootstrap and the later setup phases -
which likely would result in a decent speedup. And trialing different
max_connection and shared_buffer settings would be a lot faster without
retries.
Besides potential speedups I also think there's architectural reasons to
prefer doing some of initdb's work in the backend - it would allow to avoid
some duplicated infrastructure and avoid leaking subsystem details to one more
place outside the subsystem.
The reason I CCed Peter is that he at some point proposed ([2]/messages/by-id/61b8d18d-c922-ac99-b990-a31ba63cdcbb@2ndquadrant.com) having the
backend initialize itself via a base backup. I think if we generally moved
more of the data directory initialization into the backend that'd probably
architecturally work a bit better.
I'm not planning to work on this in the near future. But I would like to do so
at some point. And it might be worth considering pushing future additions to
initidb to be moved server-side via functions that initdb calls, rather than
having initdb control everything.
Greetings,
Andres Freund
[1]: https://bugs.winehq.org/show_bug.cgi?id=51719
[2]: /messages/by-id/61b8d18d-c922-ac99-b990-a31ba63cdcbb@2ndquadrant.com
On 9/8/21 3:07 PM, Andres Freund wrote:
Hi,
While hacking on AIO I wanted to build the windows portion from linux. That
works surprisingly well with cross-building using --host=x86_64-w64-mingw32 .What didn't work as well was running things under wine. It turns out that the
server itself works ok, but that initdb hangs because of a bug in wine ([1]),
leading to the bootstrap process hanging while trying to read more input.Which made me wonder: What is really the point of doing so much setup as part
of initdb? Of course a wine bug isn't a reason to change anything, but I see
other reasons it might be worth thinking about moving more of initdb's logic
into the backend.There of course is historical raisins for things happening in initdb - the
setup logic didn't use to be C. But now that it is C, it seems a bit absurd to
read bootstrap data in initdb, write the data to a pipe, and then read it
again in the backend. It for sure doesn't make things faster.
I guess the downside would be that we'd need to teach the backend how to
do more stuff that only needs to be done once per cluster, and then that
code would be dead space for the rest of the lifetime of the cluster.
Maybe the difference is sufficiently small that it doesn't matter.
cheers
andrew
--
Andrew Dunstan
EDB: https://www.enterprisedb.com
Hi,
On September 8, 2021 1:24:00 PM PDT, Andrew Dunstan <andrew@dunslane.net> wrote:
On 9/8/21 3:07 PM, Andres Freund wrote:
There of course is historical raisins for things happening in initdb - the
setup logic didn't use to be C. But now that it is C, it seems a bit absurd to
read bootstrap data in initdb, write the data to a pipe, and then read it
again in the backend. It for sure doesn't make things faster.I guess the downside would be that we'd need to teach the backend how to
do more stuff that only needs to be done once per cluster, and then that
code would be dead space for the rest of the lifetime of the cluster.Maybe the difference is sufficiently small that it doesn't matter.
Unused code doesn't itself cost much - the OS won't even page it in. And disk space wise, there's not much difference between code in initdb and code in postgres. It's callsites to the code that can be problematic. But there were already paying the price via --boot and a fair number of if (bootstrap) blocks.
Regards,
Andres
--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
On 08.09.21 21:07, Andres Freund wrote:
There of course is historical raisins for things happening in initdb - the
setup logic didn't use to be C. But now that it is C, it seems a bit absurd to
read bootstrap data in initdb, write the data to a pipe, and then read it
again in the backend. It for sure doesn't make things faster.
A couple of things I was looking into a while ago: We could probably
get a bit of performance by replacing the line-by-line substitutions
(replace_token()) by processing the whole buffer at once. And we could
get even more performance by not doing any post-processing of the files
at all. For example, we don't need to replace_token() SIZEOF_POINTER,
which is known at compile time. Handling ENCODING, LC_COLLATE, etc. is
not quite as obvious, but moving some of that logic into the backend
could be helpful in that direction.
On 9/8/21 5:48 PM, Andres Freund wrote:
Hi,
On September 8, 2021 1:24:00 PM PDT, Andrew Dunstan <andrew@dunslane.net> wrote:
On 9/8/21 3:07 PM, Andres Freund wrote:
There of course is historical raisins for things happening in initdb - the
setup logic didn't use to be C. But now that it is C, it seems a bit absurd to
read bootstrap data in initdb, write the data to a pipe, and then read it
again in the backend. It for sure doesn't make things faster.I guess the downside would be that we'd need to teach the backend how to
do more stuff that only needs to be done once per cluster, and then that
code would be dead space for the rest of the lifetime of the cluster.Maybe the difference is sufficiently small that it doesn't matter.
Unused code doesn't itself cost much - the OS won't even page it in. And disk space wise, there's not much difference between code in initdb and code in postgres. It's callsites to the code that can be problematic. But there were already paying the price via --boot and a fair number of if (bootstrap) blocks.
Fair enough. You're quite right, of course, the original design of
initdb.c was to do what the preceding shell script did as closely as
possible. It does leak a bit of memory, which doesn't matter in the
context of a short-lived program - but that shouldn't be too hard to
manage in the backend.
cheers
andrew
--
Andrew Dunstan
EDB: https://www.enterprisedb.com