Skip to content

PS-10595 [9.7]: Reduce rw_lock_list_mutex contention during buffer pool initialization#6039

Open
polchawa-percona wants to merge 1 commit into
percona:9.7from
polchawa-percona:PS-10595-9.7-rwlock-bulk-register
Open

PS-10595 [9.7]: Reduce rw_lock_list_mutex contention during buffer pool initialization#6039
polchawa-percona wants to merge 1 commit into
percona:9.7from
polchawa-percona:PS-10595-9.7-rwlock-bulk-register

Conversation

@polchawa-percona

@polchawa-percona polchawa-percona commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

https://perconadev.atlassian.net/browse/PS-10595

This is a contribution from Alexey Bychko abychko@gmail.com, with a
modification on top of the original patch: instead of inserting each chunk's
rw-locks into the global rw_lock_list one by one while holding
rw_lock_list_mutex, the per-chunk list is prepared outside the mutex and then
concatenated onto rw_lock_list in O(1) under the mutex.

During buffer pool initialization every buffer block rw-lock (block->lock
and, in debug builds, block->debug_latch) was registered in the global
rw_lock_list under rw_lock_list_mutex, one lock at a time. With large
buffer pools and parallel initialization this serializes heavily on that
single mutex.

Initialize block rw-locks without registering them in rw_lock_list, then
register a whole chunk's locks at once:

[+] rw_lock_init_only() initializes an rw_lock_t exactly like
rw_lock_create_func() but does not add it to rw_lock_list. A PFS-aware
wrapper pfs_rw_lock_init_only_func() and the rw_lock_init_only_inst()
macro preserve placement-new, pfs_psi and (debug) latch id handling.
[+] ut_list_concatenate() / UT_LIST_CONCATENATE() splice one UT_LIST onto
another in O(1).
[+] rw_lock_list_register_bulk() builds nothing under the lock: the caller
prepares the per-chunk list outside rw_lock_list_mutex, and this function
only splices it onto rw_lock_list in O(1) under a single mutex section.
[*] buf_block_init() now uses rw_lock_init_only_inst(); buf_pool_register_chunk()
collects the chunk's block rw-locks into a local list and registers them
in bulk.

rw_lock_create_func() keeps its existing signature and behavior, so all
other callers and diagnostics based on rw_lock_list are unaffected; the
complete rw_lock_list is available once initialization finishes.

@polchawa-percona polchawa-percona changed the title PS-10595 (9.7) Reduce rw_lock_list contention during buffer pool initialization Jun 25, 2026
@polchawa-percona polchawa-percona self-assigned this Jun 25, 2026
@polchawa-percona polchawa-percona force-pushed the PS-10595-9.7-rwlock-bulk-register branch 2 times, most recently from 1601e18 to f961ae5 Compare June 26, 2026 10:18
@polchawa-percona polchawa-percona force-pushed the PS-10595-9.7-rwlock-bulk-register branch 4 times, most recently from a2d2575 to 56d04e9 Compare June 29, 2026 15:04
@polchawa-percona polchawa-percona changed the title PS-10595 [9.7]: Reduce rw_lock_list contention during buffer pool initialization Jun 29, 2026
…tialization

https://perconadev.atlassian.net/browse/PS-10595

This is a contribution from Alexey Bychko <abychko@gmail.com>, with a
modification on top of the original patch: instead of inserting each chunk's
rw-locks into the global rw_lock_list one by one while holding
rw_lock_list_mutex, the per-chunk list is prepared outside the mutex and then
concatenated onto rw_lock_list in O(1) under the mutex.

During buffer pool initialization every buffer block rw-lock (block->lock
and, in debug builds, block->debug_latch) was registered in the global
rw_lock_list under rw_lock_list_mutex, one lock at a time. With large
buffer pools and parallel initialization this serializes heavily on that
single mutex.

Initialize block rw-locks without registering them in rw_lock_list, then
register a whole chunk's locks at once:

[+] rw_lock_init_only() initializes an rw_lock_t exactly like
    rw_lock_create_func() but does not add it to rw_lock_list. A PFS-aware
    wrapper pfs_rw_lock_init_only_func() and the rw_lock_init_only_inst()
    macro preserve placement-new, pfs_psi and (debug) latch id handling.
[+] ut_list_concatenate() / UT_LIST_CONCATENATE() splice one UT_LIST onto
    another in O(1).
[+] rw_lock_list_register_bulk() only splices a caller-prepared list onto
    rw_lock_list in O(1) under a single rw_lock_list_mutex section.
[*] buf_block_init() uses rw_lock_init_only_inst(); buf_chunk_init() builds the
    chunk's rw-lock list and registers it in bulk, exactly once per chunk
    creation. buf_pool_register_chunk() only inserts into the chunk map, since
    buf_pool_resize() re-invokes it on carried-over chunks and must not
    re-register (double-register) their locks in rw_lock_list.

rw_lock_create_func() keeps its existing signature and behavior, so all
other callers and diagnostics based on rw_lock_list are unaffected; the
complete rw_lock_list is available once initialization finishes.
@polchawa-percona polchawa-percona force-pushed the PS-10595-9.7-rwlock-bulk-register branch from 56d04e9 to d36f785 Compare June 29, 2026 15:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants