pg-perf-bench 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pg_perf_bench-0.2.0/LICENSE +21 -0
- pg_perf_bench-0.2.0/PKG-INFO +530 -0
- pg_perf_bench-0.2.0/README.md +493 -0
- pg_perf_bench-0.2.0/THIRD_PARTY_NOTICES.md +37 -0
- pg_perf_bench-0.2.0/pyproject.toml +94 -0
- pg_perf_bench-0.2.0/setup.cfg +4 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/__init__.py +3 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/__main__.py +4 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/benchmark.py +646 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/cli.py +820 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/client_tools.py +135 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/collect_info.py +180 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/cpu_info.sh +2 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/df_h.sh +3 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/etc_fstab.sh +3 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/etc_os_release.sh +3 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/ip_br_addr.sh +4 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_bridge.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_bus.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_communication.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_disk.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_display.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_generic.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_input.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_memory.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_multimedia.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_network.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_power.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_processor.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_storage.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_system.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/lshw_volume.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/mount.sh +3 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/pg_config.sh +2 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/sys_memory_total.sh +6 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/sysctl_net_ipv4_tcp.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/sysctl_net_ipv4_udp.sh +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/sysctl_vm.sh +2 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/total_ram.sh +2 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/bash_commands/uname_a.sh +3 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/sql_commands/available_server_extensions.sql +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/sql_commands/full_version.sql +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/sql_commands/pg_settings.sql +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/sql_commands/server_version.sql +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/commands/sql_commands/server_version_major.sql +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/config.py +418 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/connections/__init__.py +11 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/connections/common.py +13 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/connections/docker.py +271 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/connections/local.py +115 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/connections/ssh.py +179 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/const.py +102 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/context/__init__.py +5 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/context/base_context.py +79 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/context/benchmark.py +157 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/context/collect_info.py +125 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/context/join.py +14 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/contracts.py +121 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/db_operations/__init__.py +81 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/db_operations/conn_tasks/__init__.py +12 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/db_operations/conn_tasks/common.py +48 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/db_operations/conn_tasks/docker.py +29 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/db_operations/conn_tasks/local.py +35 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/db_operations/conn_tasks/ssh.py +32 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/db_operations/db.py +124 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/errors.py +61 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/executors/__init__.py +5 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/executors/process.py +156 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join.py +581 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_catalog.py +134 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/README.md +29 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/compare-postgresql-major/README.md +19 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/compare-postgresql-major/task.json +18 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/compare-storage/README.md +19 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/compare-storage/task.json +20 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/optimize-db-config/README.md +22 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/optimize-db-config/task.json +14 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/repeatability/README.md +17 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/repeatability/task.json +15 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/scale-cpu/README.md +19 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/scale-cpu/task.json +20 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/scale-memory/README.md +18 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/scale-memory/task.json +20 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/tune-os-kernel/README.md +17 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/join_tasks/tune-os-kernel/task.json +20 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/log.py +74 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/orchestration.py +135 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/report/__init__.py +11 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/report/commands.py +546 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/report/html.py +112 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/report/processing.py +146 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/run.py +36 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/system_metrics.py +218 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/templates/all_info_report_struct.json +274 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/templates/benchmark_report_struct.json +377 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/templates/db_info_report_struct.json +61 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/templates/report.html +806 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/templates/sys_info_report_struct.json +220 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/templates/vendor/THIRD_PARTY_LICENSES.txt +15 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/templates/vendor/echarts-6.1.0.LICENSE-d3.txt +27 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/templates/vendor/echarts-6.1.0.LICENSE.txt +222 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/templates/vendor/echarts-6.1.0.NOTICE.txt +5 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/templates/vendor/echarts-6.1.0.min.js +45 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/templates/vendor/highlight-11.11.1.LICENSE.txt +29 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/templates/vendor/highlight-11.11.1.min.js +1244 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/templates/vendor/highlight-github-dark-11.11.1.min.css +10 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/validator.py +55 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/README.md +16 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/imdb/README.md +18 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/imdb/generator.py +127 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/imdb/profile.json +25 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/imdb/sql/01_company_catalog.sql +16 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/imdb/sql/02_people_by_keyword.sql +18 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/imdb/sql/03_keyword_trends.sql +14 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/imdb/sql/04_genre_cast.sql +14 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/imdb/sql/05_join_stress.sql +22 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/imdb/sql/indexes.sql +20 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/imdb/sql/schema.sql +69 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/pagila/README.md +17 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/pagila/generator.py +203 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/pagila/profile.json +23 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/pagila/sql/01_select.sql +264 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/pagila/sql/02_insert.sql +273 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/pagila/sql/03_update.sql +149 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/pagila/sql/04_delete.sql +27 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workload_profiles/pagila/sql/pagila-schema.sql +1688 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench/workloads.py +297 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench.egg-info/PKG-INFO +530 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench.egg-info/SOURCES.txt +143 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench.egg-info/dependency_links.txt +1 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench.egg-info/entry_points.txt +2 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench.egg-info/requires.txt +24 -0
- pg_perf_bench-0.2.0/src/pg_perf_bench.egg-info/top_level.txt +1 -0
- pg_perf_bench-0.2.0/tests/test_benchmark_evidence.py +162 -0
- pg_perf_bench-0.2.0/tests/test_cli_contract.py +255 -0
- pg_perf_bench-0.2.0/tests/test_client_tools.py +36 -0
- pg_perf_bench-0.2.0/tests/test_collection_backend.py +122 -0
- pg_perf_bench-0.2.0/tests/test_db_operations.py +48 -0
- pg_perf_bench-0.2.0/tests/test_join_regressions.py +183 -0
- pg_perf_bench-0.2.0/tests/test_process_executor.py +47 -0
- pg_perf_bench-0.2.0/tests/test_report_safety.py +36 -0
- pg_perf_bench-0.2.0/tests/test_report_transport.py +91 -0
- pg_perf_bench-0.2.0/tests/test_system_metrics.py +80 -0
- pg_perf_bench-0.2.0/tests/test_transports.py +71 -0
- pg_perf_bench-0.2.0/tests/test_workload_profiles.py +128 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Tantor Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,530 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pg-perf-bench
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Reproducible PostgreSQL benchmark runner with environment evidence and portable reports
|
|
5
|
+
Author-email: O2eg <oleg.ispu@yandex.ru>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/O2eg/pg_perf_bench
|
|
8
|
+
Project-URL: Repository, https://github.com/O2eg/pg_perf_bench
|
|
9
|
+
Project-URL: Issues, https://github.com/O2eg/pg_perf_bench/issues
|
|
10
|
+
Keywords: postgresql,benchmark,pgbench,performance,diagnostics
|
|
11
|
+
Requires-Python: >=3.10
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
License-File: THIRD_PARTY_NOTICES.md
|
|
15
|
+
License-File: src/pg_perf_bench/templates/vendor/THIRD_PARTY_LICENSES.txt
|
|
16
|
+
License-File: src/pg_perf_bench/templates/vendor/echarts-6.1.0.LICENSE-d3.txt
|
|
17
|
+
License-File: src/pg_perf_bench/templates/vendor/echarts-6.1.0.LICENSE.txt
|
|
18
|
+
License-File: src/pg_perf_bench/templates/vendor/highlight-11.11.1.LICENSE.txt
|
|
19
|
+
License-File: src/pg_perf_bench/templates/vendor/echarts-6.1.0.NOTICE.txt
|
|
20
|
+
Requires-Dist: PyYAML<7,>=6.0
|
|
21
|
+
Requires-Dist: asyncpg<1,>=0.29
|
|
22
|
+
Requires-Dist: asyncssh<3,>=2.21
|
|
23
|
+
Requires-Dist: docker<8,>=7.1
|
|
24
|
+
Requires-Dist: pg-diag<1,>=0.10.3
|
|
25
|
+
Requires-Dist: aenum<4,>=3.1; python_version < "3.11"
|
|
26
|
+
Provides-Extra: test
|
|
27
|
+
Requires-Dist: pytest<9,>=8.3; extra == "test"
|
|
28
|
+
Requires-Dist: tomli>=2.0; python_version < "3.11" and extra == "test"
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: build<2,>=1.2; extra == "dev"
|
|
31
|
+
Requires-Dist: pytest<9,>=8.3; extra == "dev"
|
|
32
|
+
Requires-Dist: pytest-cov<8,>=6; extra == "dev"
|
|
33
|
+
Requires-Dist: ruff<1,>=0.12; extra == "dev"
|
|
34
|
+
Requires-Dist: tomli>=2.0; python_version < "3.11" and extra == "dev"
|
|
35
|
+
Requires-Dist: twine<7,>=6; extra == "dev"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# pg_perf_bench
|
|
39
|
+
|
|
40
|
+
## Overview
|
|
41
|
+
|
|
42
|
+
Based on [pg_perfbench](https://github.com/TantorLabs/pg_perfbench).
|
|
43
|
+
|
|
44
|
+
`pg_perf_bench` runs controlled PostgreSQL benchmarks and stores the result
|
|
45
|
+
together with the facts required to interpret it: the effective workload,
|
|
46
|
+
PostgreSQL configuration, server version, host properties, execution timing,
|
|
47
|
+
raw command output, and collection diagnostics.
|
|
48
|
+
|
|
49
|
+
Its benchmark question is maximum TPS for one workload profile and one complete
|
|
50
|
+
environment, including OS and PostgreSQL settings. `pg_workload` schedules and
|
|
51
|
+
runs workload profiles; `pg_perf_bench` sweeps load, resets the dataset for each
|
|
52
|
+
point, measures the saturation curve, and preserves the evidence needed for a
|
|
53
|
+
controlled comparison.
|
|
54
|
+
|
|
55
|
+
Every successful collection or benchmark produces two artifacts:
|
|
56
|
+
|
|
57
|
+
- a JSON document for automation and later comparison;
|
|
58
|
+
- a self-contained HTML report with embedded data, styles, ECharts,
|
|
59
|
+
highlight.js, and third-party notices.
|
|
60
|
+
|
|
61
|
+
The HTML report has no runtime network dependency. Python 3.10 or newer is
|
|
62
|
+
required.
|
|
63
|
+
|
|
64
|
+
## What the utility does
|
|
65
|
+
|
|
66
|
+
The CLI supports three groups of workflows:
|
|
67
|
+
|
|
68
|
+
- `benchmark` recreates a dedicated database before every measured iteration,
|
|
69
|
+
initializes the workload, runs it, and collects final host/database facts;
|
|
70
|
+
- `collect-sys-info`, `collect-db-info`, and `collect-all-info` gather evidence
|
|
71
|
+
without running a workload;
|
|
72
|
+
- `join` validates the comparability of existing reports and builds one
|
|
73
|
+
comparison report with combined tables, charts, logs, and benchmark evidence.
|
|
74
|
+
|
|
75
|
+
Additional commands render HTML, validate packaged content, expose component
|
|
76
|
+
capabilities, validate and summarize report artifacts, and build a deterministic
|
|
77
|
+
execution plan. The versioned [`pg_play` integration contract](doc/pg_play-integration.md)
|
|
78
|
+
documents the machine interface used by the orchestrator.
|
|
79
|
+
|
|
80
|
+
## Architecture
|
|
81
|
+
|
|
82
|
+
The backend is divided into explicit layers:
|
|
83
|
+
|
|
84
|
+
```text
|
|
85
|
+
CLI and automation contract
|
|
86
|
+
-> typed configuration and validation
|
|
87
|
+
-> benchmark / collection / join orchestration
|
|
88
|
+
-> Local, Docker, or SSH transport
|
|
89
|
+
-> PostgreSQL lifecycle and bounded process execution
|
|
90
|
+
-> report item collectors
|
|
91
|
+
-> atomic JSON and monolithic HTML persistence
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
The transport controls PostgreSQL and executes host fact collectors on the
|
|
95
|
+
selected target. The workload commands themselves run on the machine where
|
|
96
|
+
`pg_perf_bench` is invoked:
|
|
97
|
+
|
|
98
|
+
| Transport | Host facts and PostgreSQL lifecycle | `pgbench` / `psql` |
|
|
99
|
+
|---|---|---|
|
|
100
|
+
| `local` | local machine | local machine |
|
|
101
|
+
| `docker` | existing container | local machine through a published port |
|
|
102
|
+
| `ssh` | remote host | local machine through an SSH local-forwarding port |
|
|
103
|
+
|
|
104
|
+
This separation keeps workload generation independent of target management and
|
|
105
|
+
makes the measured client location explicit.
|
|
106
|
+
|
|
107
|
+
Detailed operational guides are indexed in [doc/README.md](doc/README.md).
|
|
108
|
+
|
|
109
|
+
## Installation
|
|
110
|
+
|
|
111
|
+
Create a virtual environment and install the package:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
python3 -m venv .venv
|
|
115
|
+
.venv/bin/python -m pip install --upgrade pip
|
|
116
|
+
.venv/bin/python -m pip install .
|
|
117
|
+
.venv/bin/pg-perf-bench --version
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
For development:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
python3 -m venv .venv
|
|
124
|
+
.venv/bin/python -m pip install -e ../pg_diag -e '.[dev]'
|
|
125
|
+
.venv/bin/ruff check src tests
|
|
126
|
+
.venv/bin/python -m pytest
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The source checkout is needed until the minimum supported `pg_diag` release is
|
|
130
|
+
available from the configured package index. For a PyPI release, publish
|
|
131
|
+
`pg_diag` and `pg_stand` first; the tagged build intentionally verifies those
|
|
132
|
+
declared dependencies from the package index before publishing
|
|
133
|
+
`pg_perf_bench`.
|
|
134
|
+
|
|
135
|
+
`pgbench` and `psql` must be installed on the workload-generator host.
|
|
136
|
+
`pg_perf_bench` discovers every client below `/usr/lib/postgresql/*/bin` and in
|
|
137
|
+
`PATH`, selects the newest installed version, and refuses an explicitly selected
|
|
138
|
+
older client. This keeps the load generator on the current `pgbench` even when
|
|
139
|
+
the target is PostgreSQL 10–18. The target needs the PostgreSQL server utilities
|
|
140
|
+
required for lifecycle operations. `pg_diag` and host `iostat` provide the OS
|
|
141
|
+
sampling engine used during the workload window.
|
|
142
|
+
|
|
143
|
+
## CLI
|
|
144
|
+
|
|
145
|
+
```text
|
|
146
|
+
pg-perf-bench benchmark ...
|
|
147
|
+
pg-perf-bench collect-sys-info ...
|
|
148
|
+
pg-perf-bench collect-db-info ...
|
|
149
|
+
pg-perf-bench collect-all-info ...
|
|
150
|
+
pg-perf-bench join ...
|
|
151
|
+
pg-perf-bench render ...
|
|
152
|
+
pg-perf-bench validate-artifact REPORT.json
|
|
153
|
+
pg-perf-bench summarize REPORT.json
|
|
154
|
+
pg-perf-bench validate
|
|
155
|
+
pg-perf-bench profiles
|
|
156
|
+
pg-perf-bench join-tasks
|
|
157
|
+
pg-perf-bench plan ...
|
|
158
|
+
pg-perf-bench capabilities
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Use `pg-perf-bench COMMAND --help` for the complete option list. The old
|
|
162
|
+
`--mode=COMMAND` form remains accepted as a compatibility adapter.
|
|
163
|
+
|
|
164
|
+
Common output options:
|
|
165
|
+
|
|
166
|
+
- `--report-name NAME` sets the safe base name of the JSON and HTML artifacts;
|
|
167
|
+
- `--out DIR` selects the artifact directory, default `report` (`--output-dir` is a compatibility alias);
|
|
168
|
+
- `--log-dir DIR` selects the application log directory, default `log`;
|
|
169
|
+
- `--log-level {info,debug,error}` sets verbosity;
|
|
170
|
+
- `--clear-logs` removes old `*.log` files from the selected log directory.
|
|
171
|
+
|
|
172
|
+
## Safety contract
|
|
173
|
+
|
|
174
|
+
Collection and benchmark modes have deliberately different mutation rules.
|
|
175
|
+
|
|
176
|
+
Collection:
|
|
177
|
+
|
|
178
|
+
- does not replace `postgresql.conf`;
|
|
179
|
+
- does not start or stop PostgreSQL;
|
|
180
|
+
- uses a read-only database session;
|
|
181
|
+
- applies a 10-second PostgreSQL statement timeout;
|
|
182
|
+
- records an item-level error and continues when an optional fact cannot be
|
|
183
|
+
collected.
|
|
184
|
+
|
|
185
|
+
Benchmark:
|
|
186
|
+
|
|
187
|
+
- terminates sessions connected to the selected benchmark database;
|
|
188
|
+
- drops and recreates that database from `template0` before every iteration;
|
|
189
|
+
- refuses `postgres`, `template0`, and `template1`;
|
|
190
|
+
- requires the explicit `--allow-database-reset` confirmation;
|
|
191
|
+
- drops OS filesystem caches only when `--drop-os-caches` is supplied;
|
|
192
|
+
- accepts a replacement PostgreSQL configuration only in benchmark mode.
|
|
193
|
+
|
|
194
|
+
Use only a dedicated disposable database. Prefer a disposable environment
|
|
195
|
+
provisioned by `pg_stand` for development and integration tests.
|
|
196
|
+
|
|
197
|
+
Commands supplied through `--init-command` and `--workload-command` are trusted
|
|
198
|
+
shell input. Do not run workload definitions from an untrusted source.
|
|
199
|
+
|
|
200
|
+
## Passwords and SSH trust
|
|
201
|
+
|
|
202
|
+
Supply the PostgreSQL password through `PGPASSWORD` or `--password`. The
|
|
203
|
+
legacy `--pg-password` and `--pg-user-password` aliases are also accepted. Known secret fields and the
|
|
204
|
+
effective password value are redacted from logs, plans, reports, and command
|
|
205
|
+
evidence.
|
|
206
|
+
|
|
207
|
+
SSH host-key verification is enabled by default. Provide `--ssh-known-hosts`,
|
|
208
|
+
or use the normal `~/.ssh/known_hosts`. The
|
|
209
|
+
`--ssh-insecure-no-host-key-check` switch is intended only for isolated,
|
|
210
|
+
disposable stands.
|
|
211
|
+
|
|
212
|
+
## Collecting environment facts
|
|
213
|
+
|
|
214
|
+
Host-only collection does not require PostgreSQL connection options:
|
|
215
|
+
|
|
216
|
+
```bash
|
|
217
|
+
pg-perf-bench collect-sys-info \
|
|
218
|
+
--connection-type local \
|
|
219
|
+
--report-name host-facts
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Database collection requires connection parameters and `--pg-bin-path` for
|
|
223
|
+
the packaged `pg_config` collector:
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
PGPASSWORD=secret pg-perf-bench collect-db-info \
|
|
227
|
+
--connection-type local \
|
|
228
|
+
--host 127.0.0.1 \
|
|
229
|
+
--port 5432 \
|
|
230
|
+
--user postgres \
|
|
231
|
+
--database postgres \
|
|
232
|
+
--pg-bin-path /usr/lib/postgresql/18/bin \
|
|
233
|
+
--report-name db-facts
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
`collect-all-info` combines host and database facts. A missing optional tool or
|
|
237
|
+
permission does not discard valid data: the affected item becomes `error` or
|
|
238
|
+
`partial`, artifacts are still generated, and the CLI returns exit code 5.
|
|
239
|
+
|
|
240
|
+
Local and SSH hardware collectors invoke `sudo -n lshw`; Docker mode instead
|
|
241
|
+
collects host inventory without sudo and keeps the target container's
|
|
242
|
+
`pg_config` evidence separate. Raw interface state is retained, but runtime
|
|
243
|
+
Docker bridges do not participate in the stable JOIN hardware identity.
|
|
244
|
+
|
|
245
|
+
## Running a benchmark
|
|
246
|
+
|
|
247
|
+
Exactly one iteration axis is required:
|
|
248
|
+
|
|
249
|
+
- `--pgbench-clients 1,4,16` exposes each value as
|
|
250
|
+
`ARG_PGBENCH_CLIENTS`;
|
|
251
|
+
- `--pgbench-time 10,30,60` exposes each value as `ARG_PGBENCH_TIME`.
|
|
252
|
+
|
|
253
|
+
The axis does not add pgbench options automatically; the workload command must
|
|
254
|
+
use the corresponding placeholder.
|
|
255
|
+
|
|
256
|
+
Example:
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
PGPASSWORD=secret pg-perf-bench benchmark \
|
|
260
|
+
--connection-type local \
|
|
261
|
+
--allow-database-reset \
|
|
262
|
+
--host 127.0.0.1 \
|
|
263
|
+
--port 5432 \
|
|
264
|
+
--user postgres \
|
|
265
|
+
--database pg_perf_bench_test \
|
|
266
|
+
--pg-data-path /var/lib/postgresql/18/main \
|
|
267
|
+
--pg-bin-path /usr/lib/postgresql/18/bin \
|
|
268
|
+
--benchmark-type default \
|
|
269
|
+
--pgbench-clients 1,4,16 \
|
|
270
|
+
--init-command 'ARG_PGBENCH_PATH -i -s 10 -h ARG_PG_HOST -p ARG_PG_PORT -U ARG_PG_USER ARG_PG_DATABASE' \
|
|
271
|
+
--workload-command 'ARG_PGBENCH_PATH -T 60 -c ARG_PGBENCH_CLIENTS -j ARG_PGBENCH_CLIENTS -h ARG_PG_HOST -p ARG_PG_PORT -U ARG_PG_USER ARG_PG_DATABASE' \
|
|
272
|
+
--command-timeout 120 \
|
|
273
|
+
--report-name local-pg18
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
The command timeout applies independently to initialization and workload
|
|
277
|
+
commands. It must be longer than the expected command duration.
|
|
278
|
+
|
|
279
|
+
### Workload placeholders
|
|
280
|
+
|
|
281
|
+
| Placeholder | Value source |
|
|
282
|
+
|---|---|
|
|
283
|
+
| `ARG_PG_HOST` | `--host` |
|
|
284
|
+
| `ARG_PG_PORT` | `--port` |
|
|
285
|
+
| `ARG_PG_USER` | `--user` |
|
|
286
|
+
| `ARG_PG_PASSWORD` | `--password` or `PGPASSWORD` |
|
|
287
|
+
| `ARG_PG_DATABASE` | `--database` |
|
|
288
|
+
| `ARG_PGBENCH_PATH` | newest local pgbench, or validated `--pgbench-path` |
|
|
289
|
+
| `ARG_PSQL_PATH` | matching local psql, or validated `--psql-path` |
|
|
290
|
+
| `ARG_WORKLOAD_PATH` | `--workload-path` |
|
|
291
|
+
| `ARG_WORKLOAD_SCALE` | `--workload-scale` |
|
|
292
|
+
| `ARG_PGBENCH_CLIENTS` | current client-axis value |
|
|
293
|
+
| `ARG_PGBENCH_TIME` | current duration-axis value |
|
|
294
|
+
|
|
295
|
+
Unresolved `ARG_*` placeholders fail before target mutation. Prefer
|
|
296
|
+
`PGPASSWORD` to placing `ARG_PG_PASSWORD` directly in a command line.
|
|
297
|
+
|
|
298
|
+
For a custom workload, use `--benchmark-type custom`, supply an existing
|
|
299
|
+
`--workload-path`, and reference files below that path from the command
|
|
300
|
+
templates.
|
|
301
|
+
|
|
302
|
+
For a packaged maximum-TPS workload, use `--workload-profile imdb` or
|
|
303
|
+
`--workload-profile pagila`, `--workload-scale SCALE`, and a
|
|
304
|
+
`--pgbench-clients` sweep. `pg-perf-bench profiles` lists the installed
|
|
305
|
+
collection. Each profile supplies its schema, deterministic Python generator,
|
|
306
|
+
typical SQL query set and command templates. It deliberately does not reuse
|
|
307
|
+
`pg_workload`'s scheduler-specific `profile.yml`.
|
|
308
|
+
|
|
309
|
+
### Iteration lifecycle
|
|
310
|
+
|
|
311
|
+
For each axis value the backend:
|
|
312
|
+
|
|
313
|
+
1. verifies access to the PostgreSQL instance;
|
|
314
|
+
2. drops the dedicated benchmark database;
|
|
315
|
+
3. stops PostgreSQL or the selected container;
|
|
316
|
+
4. flushes filesystems and optionally drops host OS caches;
|
|
317
|
+
5. starts PostgreSQL and recreates the database;
|
|
318
|
+
6. runs the initialization command;
|
|
319
|
+
7. runs the workload command while the `pg_diag` Linux sampler records CPU,
|
|
320
|
+
RAM, disk and network metrics on the database host;
|
|
321
|
+
8. stores raw stdout, stderr, return code, UTC start time, elapsed time, parsed
|
|
322
|
+
pgbench metrics, and iteration metadata.
|
|
323
|
+
|
|
324
|
+
After the final iteration it collects the configured host and PostgreSQL facts
|
|
325
|
+
and optionally archives PostgreSQL logs under `<output-dir>/db_logs/`, alongside
|
|
326
|
+
the JSON and HTML report artifacts.
|
|
327
|
+
|
|
328
|
+
## Transports
|
|
329
|
+
|
|
330
|
+
### Local
|
|
331
|
+
|
|
332
|
+
```bash
|
|
333
|
+
--connection-type local
|
|
334
|
+
```
|
|
335
|
+
|
|
336
|
+
Lifecycle commands use `pg_ctl` under the `postgres` account. Cache dropping
|
|
337
|
+
requires a narrow non-interactive sudo rule for the specific command.
|
|
338
|
+
|
|
339
|
+
### Docker
|
|
340
|
+
|
|
341
|
+
```bash
|
|
342
|
+
--connection-type docker \
|
|
343
|
+
--container-name pg-bench-18
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
The container must already exist. Collection refuses to start a stopped
|
|
347
|
+
container. Benchmark mode may start it because target mutation was explicitly
|
|
348
|
+
confirmed. Use normal rootless-Docker or Docker-group access; never make the
|
|
349
|
+
Docker socket world-writable.
|
|
350
|
+
|
|
351
|
+
The workload reaches PostgreSQL through the port published on `--host` and
|
|
352
|
+
`--port`.
|
|
353
|
+
|
|
354
|
+
### SSH
|
|
355
|
+
|
|
356
|
+
```bash
|
|
357
|
+
--connection-type ssh \
|
|
358
|
+
--ssh-host db-host.example \
|
|
359
|
+
--ssh-port 22 \
|
|
360
|
+
--ssh-user postgres \
|
|
361
|
+
--ssh-key /secure/path/id_ed25519 \
|
|
362
|
+
--ssh-known-hosts /secure/path/known_hosts \
|
|
363
|
+
--remote-pg-host 127.0.0.1 \
|
|
364
|
+
--remote-pg-port 5432 \
|
|
365
|
+
--host 127.0.0.1 \
|
|
366
|
+
--port 55432
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
For database modes, `--host` and `--port` are the local bind address and
|
|
370
|
+
free port. `--remote-pg-host` and `--remote-pg-port` identify PostgreSQL from
|
|
371
|
+
the SSH server. Host commands run remotely; `asyncpg`, `pgbench`, and `psql`
|
|
372
|
+
connect through native AsyncSSH local forwarding. No `AcceptEnv` change is
|
|
373
|
+
required on the SSH server.
|
|
374
|
+
|
|
375
|
+
## Report contents
|
|
376
|
+
|
|
377
|
+
A benchmark report contains:
|
|
378
|
+
|
|
379
|
+
- artifact schema and generator versions;
|
|
380
|
+
- runtime and methodology metadata;
|
|
381
|
+
- redacted effective CLI configuration;
|
|
382
|
+
- workload templates and effective commands;
|
|
383
|
+
- complete embedded SQL schemas, queries and setup scripts;
|
|
384
|
+
- complete embedded Python generator source and profile manifest;
|
|
385
|
+
- workload file hashes, scale, pgbench/psql paths, client sweep and exact
|
|
386
|
+
resolved commands;
|
|
387
|
+
- a compatibility preflight containing the PostgreSQL server major, the newest
|
|
388
|
+
local pgbench/psql versions and the supported server range 10–18;
|
|
389
|
+
- raw initialization and workload evidence for every completed iteration;
|
|
390
|
+
- parsed clients, duration, transaction count, average latency, initial
|
|
391
|
+
connection time, and TPS;
|
|
392
|
+
- an explicit `maximum_tps` point with its axis value and complete metrics;
|
|
393
|
+
- a TPS chart for the selected axis;
|
|
394
|
+
- all `pg_diag` OS charts collected during every measured iteration: CPU
|
|
395
|
+
utilization/load, RAM usage/pressure, disk throughput/IOPS/utilization/latency,
|
|
396
|
+
and network throughput/packets;
|
|
397
|
+
- PostgreSQL version, available extensions, and server settings;
|
|
398
|
+
- host, kernel, CPU, memory, storage, network, and filesystem facts;
|
|
399
|
+
- item-level collection status and diagnostic reason;
|
|
400
|
+
- an optional PostgreSQL log archive reference backed by the report-local
|
|
401
|
+
`db_logs/` directory.
|
|
402
|
+
|
|
403
|
+
The JSON and HTML files are written through temporary files and atomically
|
|
404
|
+
renamed into place. Report names cannot contain path separators, `.`/`..`, or a
|
|
405
|
+
NUL byte.
|
|
406
|
+
|
|
407
|
+
Render a JSON report again without rerunning a benchmark:
|
|
408
|
+
|
|
409
|
+
```bash
|
|
410
|
+
pg-perf-bench render \
|
|
411
|
+
--from-json report/local-pg18.json \
|
|
412
|
+
--out report/local-pg18.html
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
## Joining reports
|
|
416
|
+
|
|
417
|
+
Join mode requires at least two benchmark reports with:
|
|
418
|
+
|
|
419
|
+
- unique internal `report_name` values;
|
|
420
|
+
- the same `artifact_schema_version`;
|
|
421
|
+
- complete benchmark chart and result-table structures;
|
|
422
|
+
- equal values at every dotted path listed by the selected join task.
|
|
423
|
+
|
|
424
|
+
The explicitly selected reference remains immutable while every other report
|
|
425
|
+
is compared with it. Non-required differences become report/value comparison
|
|
426
|
+
tables. TPS chart series, pgbench result tables, log references, and raw
|
|
427
|
+
`benchmark_runs` evidence are deep-copied into the joined artifact. OS chart
|
|
428
|
+
blocks are intentionally stacked vertically by source report and iteration;
|
|
429
|
+
CPU profiles therefore remain visually comparable instead of being overlaid.
|
|
430
|
+
|
|
431
|
+
```bash
|
|
432
|
+
pg-perf-bench join \
|
|
433
|
+
--input-dir report/runs \
|
|
434
|
+
--reference-report local-pg18.json \
|
|
435
|
+
--join-task optimize-db-config \
|
|
436
|
+
--out report/comparisons \
|
|
437
|
+
--report-name clients-comparison
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
The input directory should contain only source JSON reports intended for that
|
|
441
|
+
comparison. Invalid non-reference JSON files are skipped with a warning. A
|
|
442
|
+
missing, invalid, or structurally incompatible reference fails the operation.
|
|
443
|
+
`pg-perf-bench join-tasks` lists the packaged JOIN catalog of separately
|
|
444
|
+
documented practical scenarios:
|
|
445
|
+
`optimize-db-config`, `scale-cpu`, `scale-memory`, `compare-storage`,
|
|
446
|
+
`tune-os-kernel`, `compare-postgresql-major`, and `repeatability`. Each scenario
|
|
447
|
+
fixes the evidence required by its performance question and permits only its
|
|
448
|
+
declared variable to differ. Definitions and README files are validated by
|
|
449
|
+
`pg-perf-bench validate`. The historic
|
|
450
|
+
`task_compare_dbs_on_single_host.json` name remains an alias for
|
|
451
|
+
`optimize-db-config`.
|
|
452
|
+
|
|
453
|
+
## Automation contract
|
|
454
|
+
|
|
455
|
+
`--machine` emits one JSON envelope on stdout and sends logs to stderr. It may
|
|
456
|
+
appear before or after the subcommand. `--request-id` is copied to the envelope.
|
|
457
|
+
|
|
458
|
+
```bash
|
|
459
|
+
pg-perf-bench --machine --request-id run-42 capabilities
|
|
460
|
+
pg-perf-bench --machine --request-id capabilities-42 --component-capabilities
|
|
461
|
+
pg-perf-bench --machine validate
|
|
462
|
+
pg-perf-bench --machine plan collect-sys-info --connection-type local
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
`plan` validates and redacts a configuration, then produces a deterministic
|
|
466
|
+
SHA-256 plan hash without touching the target. A machine-mode `benchmark` must
|
|
467
|
+
carry that reviewed hash. The hash includes custom workload file or directory
|
|
468
|
+
content, but excludes output paths, log settings, report name, and request id:
|
|
469
|
+
|
|
470
|
+
```bash
|
|
471
|
+
pg-perf-bench --machine plan benchmark BENCHMARK_OPTIONS...
|
|
472
|
+
pg-perf-bench --machine benchmark BENCHMARK_OPTIONS... --plan-hash sha256:...
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
All component capabilities use `pg_play/capabilities/v1`; every command declares
|
|
476
|
+
`mutates_target`, `machine_output`, and `accepts_plan_hash`. Generated artifacts
|
|
477
|
+
carry an absolute path, SHA-256 hash, size, kind, and schema version.
|
|
478
|
+
|
|
479
|
+
Stable exit codes:
|
|
480
|
+
|
|
481
|
+
| Code | Meaning |
|
|
482
|
+
|---:|---|
|
|
483
|
+
| 0 | success |
|
|
484
|
+
| 2 | invalid CLI or configuration |
|
|
485
|
+
| 3 | missing precondition or inaccessible dependency |
|
|
486
|
+
| 4 | unsupported operation |
|
|
487
|
+
| 5 | report generated with partial collection results |
|
|
488
|
+
| 6 | execution failure |
|
|
489
|
+
| 7 | cancelled operation |
|
|
490
|
+
| 8 | ownership error |
|
|
491
|
+
| 130 | interrupted by the user |
|
|
492
|
+
|
|
493
|
+
## Validation and tests
|
|
494
|
+
|
|
495
|
+
Validate the installed templates, command references, Python collectors, and
|
|
496
|
+
join task definitions:
|
|
497
|
+
|
|
498
|
+
```bash
|
|
499
|
+
pg-perf-bench validate
|
|
500
|
+
```
|
|
501
|
+
|
|
502
|
+
Run the non-destructive test suite:
|
|
503
|
+
|
|
504
|
+
```bash
|
|
505
|
+
python -m pytest
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
Integration tests are excluded by default. The supported end-to-end smoke test
|
|
509
|
+
uses an explicitly provisioned disposable `pg_stand` environment:
|
|
510
|
+
|
|
511
|
+
```bash
|
|
512
|
+
PG_PERF_BENCH_PG_STAND_INTEGRATION=1 \
|
|
513
|
+
python -m pytest -m integration tests/integration/test_pg_stand_smoke.py
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
The legacy direct-Docker integration module is disabled unless
|
|
517
|
+
`PG_PERF_BENCH_LEGACY_DOCKER_INTEGRATION=1` is set.
|
|
518
|
+
|
|
519
|
+
## Current scope
|
|
520
|
+
|
|
521
|
+
The current report captures static environment facts and final PostgreSQL
|
|
522
|
+
state. It does not yet provide continuous CPU, disk, network, wait-event, or
|
|
523
|
+
`pg_stat_*` time-series sampling during the workload. Statistical repetitions,
|
|
524
|
+
warm-up runs, and confidence intervals are outside the current execution model.
|
|
525
|
+
|
|
526
|
+
## License
|
|
527
|
+
|
|
528
|
+
The project is distributed under the MIT License. Embedded third-party assets
|
|
529
|
+
retain their own license and notice files under
|
|
530
|
+
`src/pg_perf_bench/templates/vendor/` and in `THIRD_PARTY_NOTICES.md`.
|