Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid redundand memory allocation and sycnhronization in walredo #144

Merged
merged 4 commits into from
Apr 23, 2022

Conversation

knizhnik
Copy link

No description provided.

src/backend/tcop/zenith_wal_redo.c Outdated Show resolved Hide resolved
Comment on lines +321 to +323
MemoryContextSwitchTo(MessageContext);
initStringInfo(&input_message);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes us vulnerable to memory leaks. I guess that's OK; redo functions should not leak memory, or that would be a problem with normal WAL recovery too. We just have to be careful to not leak memory in our code in this file.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately there is no fast way to get memory context size, otherwise I can add assert that size of MessageContext is not exceeding some limit.

src/backend/tcop/zenith_wal_redo.c Show resolved Hide resolved
src/backend/tcop/zenith_wal_redo.c Outdated Show resolved Hide resolved
src/backend/storage/buffer/bufmgr.c Show resolved Hide resolved
src/backend/storage/buffer/bufmgr.c Outdated Show resolved Hide resolved
@@ -41,6 +41,9 @@ inmem_init(void)
{
HASHCTL hashCtl;

if (inmem_files && hash_get_num_entries(inmem_files) == 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this make any difference? Every WAL redo call dirties a page, so 'inmem_files' will never be empty.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do one of the following:

  • make the hash table smaller; 1024 is much larger than is needed for any WAL record,
  • switch to simplehash. It's faster and has a reset-function,
  • switch to a simple array instead of a hash table. Almost all WAL records touch 1-4 pages, and linear scanning a simple array is faster than a hash table with such small numbers.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this make any difference? Every WAL redo call dirties a page, so 'inmem_files' will never be empty.

Oh, I think I get it now. These functions are only used for pages that are evicted from the buffer cache. That should pretty much never happen with a WAL redo function. Replaying a record won't affect more than a handful of pages. XLR_MAX_BLOCK_ID is 32, so not more than that, actually. Are inmem_write() and inmem_read() dead code in practice?

In any case, let's add comments about that!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And let's do this:

diff --git a/src/backend/tcop/zenith_wal_redo.c b/src/backend/tcop/zenith_wal_redo.c
index 724c4d56bf..3cf4f0ef97 100644
--- a/src/backend/tcop/zenith_wal_redo.c
+++ b/src/backend/tcop/zenith_wal_redo.c
@@ -176,6 +176,8 @@ WalRedoMain(int argc, char *argv[],
 	 */
 	InitializeGUCOptions();
 
+	num_temp_buffers = 64;
+
 	/*
 	 * Parse command-line options.
 	 * TODO

The default num_temp_buffers is 1024, which is much more than we need. And DropRelFileNodeAllLocalBuffers() scans through all buffers. In my quick profiling with 'perf', DropRelFileNodeAllLocalBuffers() was taking about 10% of the CPU time (of the WAL redo process), and after changing it to 64, it's not visible in the profile anymore.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this make any difference? Every WAL redo call dirties a page, so 'inmem_files' will never be empty.

Oh, I think I get it now. These functions are only used for pages that are evicted from the buffer cache. That should pretty much never happen with a WAL redo function. Replaying a record won't affect more than a handful of pages. XLR_MAX_BLOCK_ID is 32, so not more than that, actually. Are inmem_write() and inmem_read() dead code in practice?

In any case, let's add comments about that!

As far as I remember there are some cases when wal redo writes data directly to file, bypassing shared buffers. This is why this inmem_file is needed. Without it (without resetting files) some tests didn't pass.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do one of the following:

Actually even 32 (XLR_MAX_BLOCK_ID) pages are not needed because during recovery we restore only target page and ignoring all other.

I will try to check once again what is the maximal number of pages dirtied during wal redo (when it can be larger than 1).

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And let's do this:

Makes sense: will do.

@@ -313,24 +318,23 @@ WalRedoMain(int argc, char *argv[],
/*
* Main processing loop
*/
MemoryContextSwitchTo(MessageContext);
initStringInfo(&input_message);

for (;;)
{
/*
* Release storage left over from prior query cycle, and create a new
* query input buffer in the cleared MessageContext.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"cleared MessageContext" isn't accurate anymore, as we don't reset in the loop anymore.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix this comment

@knizhnik
Copy link
Author

I removed hash from inmem_smgr, reduce maximal size of pages to 4 and use sequential search for it.
Why 4? Just because 2 is not enough. Some XLOG records updating multiple forks requires more than 2 pages.
With 4 pages test_pg_regress is passed.

I also reduced number of temporary buffers to 128. 64 is not enough: hash initialization requires more buffers.

So I do not want to say that this limits (4 for inmem_smgr and 128 for num_temp_buffers) are absolutely safe.
I just checked that regression tests are passed with them.
We can leave simple hash implementation for inmem_smgr.

@knizhnik knizhnik requested a review from hlinnaka April 22, 2022 07:14
Add comments on 'inmem_smgr.c', remove superfluous copy-pasted comments,
pgindent.
@hlinnaka
Copy link
Contributor

Added a commit with some minor cleanup here. Please squash before pushing

@knizhnik knizhnik merged commit 17213ed into main Apr 23, 2022
@knizhnik knizhnik deleted the wal_redo_optimization branch April 23, 2022 05:52
hlinnaka added a commit to neondatabase/neon that referenced this pull request Apr 28, 2022
This brings us the performance improvements to WAL redo from
neondatabase/postgres#144
knizhnik pushed a commit to neondatabase/neon that referenced this pull request May 3, 2022
This brings us the performance improvements to WAL redo from
neondatabase/postgres#144
knizhnik pushed a commit to neondatabase/neon that referenced this pull request May 3, 2022
This brings us the performance improvements to WAL redo from
neondatabase/postgres#144
MMeent pushed a commit that referenced this pull request Jul 7, 2022
* Avoid redundand memory allocation and sycnhronization in walredo

* Address review comments

* Reduce number of temp buffers and size of inmem file storage for wal redo postgres

* Misc cleanup

Add comments on 'inmem_smgr.c', remove superfluous copy-pasted comments,
pgindent.

Co-authored-by: Heikki Linnakangas <heikki.linnakangas@iki.fi>
MMeent pushed a commit that referenced this pull request Aug 18, 2022
* Avoid redundand memory allocation and sycnhronization in walredo

* Address review comments

* Reduce number of temp buffers and size of inmem file storage for wal redo postgres

* Misc cleanup

Add comments on 'inmem_smgr.c', remove superfluous copy-pasted comments,
pgindent.

Co-authored-by: Heikki Linnakangas <heikki.linnakangas@iki.fi>
lubennikovaav pushed a commit that referenced this pull request Nov 21, 2022
* Avoid redundand memory allocation and sycnhronization in walredo

* Address review comments

* Reduce number of temp buffers and size of inmem file storage for wal redo postgres

* Misc cleanup

Add comments on 'inmem_smgr.c', remove superfluous copy-pasted comments,
pgindent.

Co-authored-by: Heikki Linnakangas <heikki.linnakangas@iki.fi>
MMeent pushed a commit that referenced this pull request Feb 10, 2023
* Avoid redundand memory allocation and sycnhronization in walredo

* Address review comments

* Reduce number of temp buffers and size of inmem file storage for wal redo postgres

* Misc cleanup

Add comments on 'inmem_smgr.c', remove superfluous copy-pasted comments,
pgindent.

Co-authored-by: Heikki Linnakangas <heikki.linnakangas@iki.fi>
MMeent pushed a commit that referenced this pull request Feb 10, 2023
* Avoid redundand memory allocation and sycnhronization in walredo

* Address review comments

* Reduce number of temp buffers and size of inmem file storage for wal redo postgres

* Misc cleanup

Add comments on 'inmem_smgr.c', remove superfluous copy-pasted comments,
pgindent.

Co-authored-by: Heikki Linnakangas <heikki.linnakangas@iki.fi>
MMeent pushed a commit that referenced this pull request May 11, 2023
* Avoid redundand memory allocation and sycnhronization in walredo

* Address review comments

* Reduce number of temp buffers and size of inmem file storage for wal redo postgres

* Misc cleanup

Add comments on 'inmem_smgr.c', remove superfluous copy-pasted comments,
pgindent.

Co-authored-by: Heikki Linnakangas <heikki.linnakangas@iki.fi>
tristan957 pushed a commit that referenced this pull request Aug 10, 2023
* Avoid redundand memory allocation and sycnhronization in walredo

* Address review comments

* Reduce number of temp buffers and size of inmem file storage for wal redo postgres

* Misc cleanup

Add comments on 'inmem_smgr.c', remove superfluous copy-pasted comments,
pgindent.

Co-authored-by: Heikki Linnakangas <heikki.linnakangas@iki.fi>
tristan957 pushed a commit that referenced this pull request Nov 8, 2023
* Avoid redundand memory allocation and sycnhronization in walredo

* Address review comments

* Reduce number of temp buffers and size of inmem file storage for wal redo postgres

* Misc cleanup

Add comments on 'inmem_smgr.c', remove superfluous copy-pasted comments,
pgindent.

Co-authored-by: Heikki Linnakangas <heikki.linnakangas@iki.fi>
tristan957 pushed a commit that referenced this pull request Nov 8, 2023
* Avoid redundand memory allocation and sycnhronization in walredo

* Address review comments

* Reduce number of temp buffers and size of inmem file storage for wal redo postgres

* Misc cleanup

Add comments on 'inmem_smgr.c', remove superfluous copy-pasted comments,
pgindent.

Co-authored-by: Heikki Linnakangas <heikki.linnakangas@iki.fi>
tristan957 pushed a commit that referenced this pull request Feb 5, 2024
* Avoid redundand memory allocation and sycnhronization in walredo

* Address review comments

* Reduce number of temp buffers and size of inmem file storage for wal redo postgres

* Misc cleanup

Add comments on 'inmem_smgr.c', remove superfluous copy-pasted comments,
pgindent.

Co-authored-by: Heikki Linnakangas <heikki.linnakangas@iki.fi>
tristan957 pushed a commit that referenced this pull request Feb 5, 2024
* Avoid redundand memory allocation and sycnhronization in walredo

* Address review comments

* Reduce number of temp buffers and size of inmem file storage for wal redo postgres

* Misc cleanup

Add comments on 'inmem_smgr.c', remove superfluous copy-pasted comments,
pgindent.

Co-authored-by: Heikki Linnakangas <heikki.linnakangas@iki.fi>
tristan957 pushed a commit that referenced this pull request Feb 6, 2024
* Avoid redundand memory allocation and sycnhronization in walredo

* Address review comments

* Reduce number of temp buffers and size of inmem file storage for wal redo postgres

* Misc cleanup

Add comments on 'inmem_smgr.c', remove superfluous copy-pasted comments,
pgindent.

Co-authored-by: Heikki Linnakangas <heikki.linnakangas@iki.fi>
tristan957 pushed a commit that referenced this pull request May 10, 2024
* Avoid redundand memory allocation and sycnhronization in walredo

* Address review comments

* Reduce number of temp buffers and size of inmem file storage for wal redo postgres

* Misc cleanup

Add comments on 'inmem_smgr.c', remove superfluous copy-pasted comments,
pgindent.

Co-authored-by: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants