PostgreSQL 18 preview - 高并发性能优化 之 fast-path lock优化
PostgreSQL 18 preview - 高并发性能优化 之 fast-path lock优化
在 PostgreSQL 中,fast-path locks 是一种轻量级的锁机制,用于优化对某些锁(如关系锁)的获取和释放。它们通过避免访问共享锁表(Lock Manager)来提高性能。
每个后端进程在 PostgreSQL 中都有一个 PGPROC 结构,用于存储进程的状态信息,包括 fast-path locks。
在之前的实现中,FastPathTransferRelationLocks() 和 GetLockConflicts() 函数在每次迭代时都会重新计算 fast-path group,即使它是常量。此外,它们会扫描空的 fast-path group,导致不必要的性能开销。
这个 Patch 的主要目的是优化在 FastPathTransferRelationLocks() 和 GetLockConflicts() 函数中迭代 PGPROC 结构以搜索 fast-path locks 的效率。
https://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=e80171d57c25caf4362a7de17e96195f905386ea
Optimize iteration over PGPROC for fast-path lock searches.
author Fujii Masao <[email protected]>
Fri, 14 Mar 2025 13:49:29 +0000 (22:49 +0900)
committer Fujii Masao <[email protected]>
Fri, 14 Mar 2025 13:49:29 +0000 (22:49 +0900)
commit e80171d57c25caf4362a7de17e96195f905386ea
tree caaf9871da2c99d6dfc2e4b6cca03af7f3cc43f7 tree
parent a359d3701991d040bf7b66cfa7052546eb923c38 commit | diff
Optimize iteration over PGPROC for fast-path lock searches. This commit improves efficiency in FastPathTransferRelationLocks()
and GetLockConflicts(), which iterate over PGPROCs to search for
fast-path locks.
Previously, these functions recalculated the fast-path group during
every loop iteration, even though it remained constant. This update
optimizes the process by calculating the group once and reusing it
throughout the loop.
The functions also now skip empty fast-path groups, avoiding
unnecessary scans of their slots. Additionally, groups belonging to
inactive backends (with pid=0) are always empty, so checking
the group is sufficient to bypass these backends, further enhancing
performance.
Author: Fujii Masao <[email protected]>
Reviewed-by: Heikki Linnakangas <[email protected]>
Reviewed-by: Ashutosh Bapat <[email protected]>
Discussion: https://postgr.es/m/[email protected]
AI解读 Patch: 优化 PGPROC 迭代以加速 fast-path lock 搜索
这个 Patch 的主要目的是优化在 FastPathTransferRelationLocks() 和 GetLockConflicts() 函数中迭代 PGPROC 结构以搜索 fast-path locks 的效率。以下是详细的解读和扩展思考。
1. 背景
Fast-path locks: 在 PostgreSQL 中,fast-path locks 是一种轻量级的锁机制,用于优化对某些锁(如关系锁)的获取和释放。它们通过避免访问共享锁表(Lock Manager)来提高性能。 PGPROC: 每个后端进程在 PostgreSQL 中都有一个 PGPROC结构,用于存储进程的状态信息,包括 fast-path locks。问题: 在之前的实现中, FastPathTransferRelationLocks()和GetLockConflicts()函数在每次迭代时都会重新计算 fast-path group,即使它是常量。此外,它们会扫描空的 fast-path group,导致不必要的性能开销。
2. Patch 的改进
Patch 对 FastPathTransferRelationLocks() 和 GetLockConflicts() 进行了以下优化:
(1) 减少重复计算
原实现: 在每次迭代时重新计算 fast-path group。 新实现: 在循环开始前计算 fast-path group 并复用,避免重复计算。 优点: 减少 CPU 开销,提高性能。
(2) 跳过空的 fast-path group
原实现: 扫描所有 fast-path group,包括空的 group。 新实现: 跳过空的 fast-path group,避免不必要的扫描。 优点: 减少不必要的迭代,提高性能。
(3) 跳过 inactive 后端
原实现: 需要检查每个后端的活跃状态(通过 pid=0判断)。新实现: 如果 fast-path group 为空,则直接跳过 inactive 后端。 优点: 减少对 inactive 后端的检查,提高性能。
3. 代码示例
以下是 Patch 修改前后的代码对比:
修改前
for (i = 0; i < ProcGlobal->allProcCount; i++) {
PGPROC *proc = &ProcGlobal->allProcs[i];
int fpidx = FAST_PATH_GET_GROUP(proc);
if (proc->pid == 0)
continue;
for (j = 0; j < FP_LOCK_SLOTS_PER_GROUP; j++) {
if (proc->fpLockBits & (1 << j)) {
// Process fast-path lock
}
}
}
修改后
for (i = 0; i < ProcGlobal->allProcCount; i++) {
PGPROC *proc = &ProcGlobal->allProcs[i];
int fpidx = FAST_PATH_GET_GROUP(proc);
if (proc->fpLockBits == 0)
continue;
for (j = 0; j < FP_LOCK_SLOTS_PER_GROUP; j++) {
if (proc->fpLockBits & (1 << j)) {
// Process fast-path lock
}
}
}
4. 扩展思考: 什么时候会用到 fast-path lock?
Fast-path locks 主要用于以下场景:
关系锁(Relation Locks): 当获取或释放表、索引等关系对象的锁时,fast-path locks 可以避免访问共享锁表,从而提高性能。 高并发场景: 在高并发环境中,fast-path locks 可以减少锁管理器的争用,提高系统的吞吐量。 短事务: 对于短事务,fast-path locks 可以显著减少锁获取和释放的开销。
5. 能优化哪些场景的性能?
Patch 的优化对以下场景的性能有显著提升:
高并发锁争用: 当多个后端进程频繁获取和释放 fast-path locks 时,减少迭代和重复计算可以显著降低 CPU 开销。 大量 inactive 后端: 当系统中有大量 inactive 后端时,跳过空的 fast-path group 可以减少不必要的扫描。 锁冲突检测: 在 GetLockConflicts()中,优化后的迭代可以更快地检测锁冲突,提高查询的执行效率。
6. 总结
这个 Patch 通过以下方式优化了 fast-path lock 的搜索性能:
减少重复计算 fast-path group。 跳过空的 fast-path group。 跳过 inactive 后端。
这些改进在高并发、大量 inactive 后端和锁冲突检测等场景中能够显著提升性能。对于 DBA 和开发者来说,这意味着更高效的锁管理和更好的系统吞吐量。