Skip to content

Commit 533d2bd

Browse files
Merge pull request #2076 from jasonrandrews/review
Update BOLT merge Learning Path
2 parents 2c7a9c1 + 105b7fb commit 533d2bd

File tree

4 files changed

+240
-104
lines changed

4 files changed

+240
-104
lines changed

content/learning-paths/servers-and-cloud-computing/bolt-merge/how-to-2.md

Lines changed: 138 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ Configure the build for debug:
3434

3535
```bash
3636
mkdir build && cd build
37-
cmake .. -DCMAKE_C_FLAGS="-O3 -mcpu=neoverse-n2 -Wno-enum-constexpr-conversion -fno-reorder-blocks-and-partition" \
38-
-DCMAKE_CXX_FLAGS="-O3 -mcpu=neoverse-n2 -Wno-enum-constexpr-conversion -fno-reorder-blocks-and-partition" \
37+
cmake .. -DCMAKE_C_FLAGS="-O3 -march=native -Wno-enum-constexpr-conversion -fno-reorder-blocks-and-partition" \
38+
-DCMAKE_CXX_FLAGS="-O3 -march=native -Wno-enum-constexpr-conversion -fno-reorder-blocks-and-partition" \
3939
-DCMAKE_CXX_LINK_FLAGS="-Wl,--emit-relocs" -DCMAKE_C_LINK_FLAGS="-Wl,--emit-relocs" -G Ninja \
4040
-DWITH_BOOST=$HOME/boost -DDOWNLOAD_BOOST=On -DWITH_ZLIB=bundled -DWITH_LZ4=system -DWITH_SSL=system
4141
```
@@ -91,83 +91,97 @@ The partial output is:
9191

9292
If the symbols are missing, rebuild the binary with debug info and no stripping.
9393

94-
## Instrument the binary with BOLT
9594

96-
Use `llvm-bolt` to create an instrumented version of the binary:
95+
## Prepare MySQL server before running workloads
96+
97+
Before running the workload, you may need to initialize a new data directory if this is your first run:
9798

9899
```bash
99-
llvm-bolt $HOME/mysql-server/build/runtime_output_directory/mysqld \
100-
-instrument \
101-
-o $HOME/mysql-server/build/runtime_output_directory/mysqld.instrumented \
102-
--instrumentation-file=$HOME/mysql-server/build/profile-readonly.fdata \
103-
--instrumentation-sleep-time=5 \
104-
--instrumentation-no-counters-clear \
105-
--instrumentation-wait-forks
100+
# Initialize a new data directory
101+
# Run this from the root of your MySQL source directory (e.g. $HOME/mysql-server). This creates an empty database in the data/ directory.
102+
bin/mysqld --initialize-insecure --datadir=data
106103
```
107104

108-
### Explanation of key options
109-
110-
- `-instrument`: Enables profile generation instrumentation
111-
- `--instrumentation-file`: Path where the profile output will be saved
112-
- `--instrumentation-wait-forks`: Ensures the instrumentation continues through forks (important for daemon processes)
113-
114-
115-
## Start the instrumented MySQL server
116-
117-
Before running the workload, start the instrumented MySQL server in a separate terminal. You may need to initialize a new data directory if this is your first run:
105+
Start the instrumented server. On an 8-core system, use available cores (e.g., 2 for mysqld, 7 for sysbench). Run the command from build directory.
118106

119107
```bash
120-
# Initialize a new data directory (if needed)
121-
$HOME/mysql-server/build/runtime_output_directory/mysqld.instrumented --initialize-insecure --datadir=$HOME/mysql-bolt-data
122-
123-
# Start the instrumented server
124-
# On an 8-core system, use available cores (e.g., 6 for mysqld, 7 for sysbench)
125-
taskset -c 6 $HOME/mysql-server/build/runtime_output_directory/mysqld.instrumented \
126-
--datadir=$HOME/mysql-bolt-data \
127-
--socket=$HOME/mysql-bolt.sock \
128-
--port=3306 \
129-
--user=$(whoami) &
108+
taskset -c 2 ./bin/mysqld \
109+
--datadir=data \
110+
--max-connections=64 \
111+
--back-log=10000 \
112+
--innodb-buffer-pool-instances=128 \
113+
--innodb-file-per-table \
114+
--innodb-sync-array-size=1024 \
115+
--innodb-flush-log-at-trx-commit=1 \
116+
--innodb-io-capacity=5000 \
117+
--innodb-io-capacity-max=10000 \
118+
--tmp-table-size=16M \
119+
--max-heap-table-size=16M \
120+
--log-bin=1 \
121+
--sync-binlog=1 \
122+
--innodb-stats-persistent \
123+
--innodb-read-io-threads=4 \
124+
--innodb-write-io-threads=4 \
125+
--key-buffer-size=16M \
126+
--max-allowed-packet=16M \
127+
--max-prepared-stmt-count=2000000 \
128+
--innodb-flush-method=fsync \
129+
--innodb-log-buffer-size=64M \
130+
--read-buffer-size=262144 \
131+
--read-rnd-buffer-size=524288 \
132+
--binlog-format=MIXED \
133+
--innodb-purge-threads=1 \
134+
--table-open-cache=8000 \
135+
--table-open-cache-instances=16 \
136+
--open-files-limit=1048576 \
137+
--default-authentication-plugin=mysql_native_password
130138
```
131139

132140
Adjust `--datadir`, `--socket`, and `--port` as needed for your environment. Make sure the server is running and accessible before proceeding.
133141

134-
With the database running, open a second terminal to run the client commands.
135-
136-
## Install sysbench
137-
138-
You will need sysbench to generate workloads for MySQL. On most Arm Linux distributions, you can install it using your package manager:
142+
With the database running, open a second terminal to create a benchmark User and third terminal to run the client commands.
139143

144+
## Create Benchmark User and Database
145+
Run once after initializing MySQL for the first time:
140146
```bash
141-
sudo apt update
142-
sudo apt install -y sysbench
147+
bin/mysql -u root <<< "
148+
CREATE USER 'bench'@'localhost' IDENTIFIED BY 'bench';
149+
CREATE DATABASE bench;
150+
GRANT ALL PRIVILEGES ON *.* TO 'bench'@'localhost' WITH GRANT OPTION;
151+
FLUSH PRIVILEGES;"
143152
```
144153

145-
Alternatively, see the [sysbench GitHub page](https://github.com/akopytov/sysbench) for build-from-source instructions if a package is not available for your platform.
154+
This sets up the bench user and the bench database with full privileges. Do not repeat this before every test — it is only required once.
146155

147-
## Create a test database and user
156+
## Reset Benchmark Database Between Runs
148157

149-
For sysbench to work, you need a test database and user. Connect to the MySQL server as the root user (or another admin user) and run:
158+
This clears all existing tables and data from the bench database, giving you a clean slate for sysbench prepare without needing to recreate the user or reinitialize the datadir.
150159

151160
```bash
152-
mysql -u root --socket=$HOME/mysql-bolt.sock
161+
bin/mysql -u root <<< "DROP DATABASE bench; CREATE DATABASE bench;"
153162
```
154163

155-
Then, in the MySQL shell:
164+
## Install and build sysbench
165+
166+
In the third terminal, do the below if you do not have sysbench already.
156167

157-
```sql
158-
CREATE DATABASE IF NOT EXISTS bench;
159-
CREATE USER IF NOT EXISTS 'bench'@'localhost' IDENTIFIED BY 'bench';
160-
GRANT ALL PRIVILEGES ON bench.* TO 'bench'@'localhost';
161-
FLUSH PRIVILEGES;
162-
EXIT;
168+
```bash
169+
git clone https://github.com/akopytov/sysbench.git
170+
cd sysbench
171+
./autogen.sh
172+
./configure
173+
make -j$(nproc)
174+
export LD_LIBRARY_PATH=/usr/local/mysql/lib/
163175
```
164176

165-
## Run the instrumented binary under a feature-specific workload
177+
Use `./src/sysbench` for running benchmarks unless installed globally.
178+
179+
## Create a dataset with sysbench
166180

167181
Run `sysbench` with the `prepare` option:
168182

169183
```bash
170-
sysbench \
184+
./src/sysbench \
171185
--db-driver=mysql \
172186
--mysql-host=127.0.0.1 \
173187
--mysql-db=bench \
@@ -177,13 +191,68 @@ sysbench \
177191
--tables=8 \
178192
--table-size=10000 \
179193
--threads=1 \
180-
/usr/share/sysbench/oltp_read_only.lua prepare
194+
src/lua/oltp_read_write.lua prepare
195+
```
196+
197+
Navigate out of the `sysbench` directory.
198+
199+
```bash
200+
cd ..
201+
```
202+
203+
## Shutdown MySQL and snapshot dataset for fast reuse
204+
205+
Do these steps once at the start from MySQL source directory
206+
207+
```bash
208+
bin/mysqladmin -u root shutdown
209+
mv data data-orig
181210
```
182211

212+
This saves the populated dataset before benchmarking.
213+
214+
```bash
215+
rm -rf /dev/shm/dataset
216+
cp -R data-orig/ /dev/shm/dataset
217+
```
218+
219+
From MySQL source directory,
220+
221+
```bash
222+
ln -s /dev/shm/dataset/ data
223+
```
224+
225+
This links the MySQL --datadir to a fast in-memory copy, ensuring every test starts from a clean, identical state.
226+
227+
## Instrument the binary with BOLT
228+
229+
Use `llvm-bolt` to create an instrumented version of the binary:
230+
231+
```bash
232+
llvm-bolt $HOME/mysql-server/build/bin/mysqld \
233+
-instrument \
234+
-o $HOME/mysql-server/build/bin/mysqldreadonly.instrumented \
235+
--instrumentation-file=$HOME/mysql-server/build/profile-readonly.fdata \
236+
--instrumentation-sleep-time=5 \
237+
--instrumentation-no-counters-clear \
238+
--instrumentation-wait-forks \
239+
2>&1 | tee $HOME/mysql-server/bolt-instrumentation-readonly.log
240+
```
241+
242+
### Explanation of key options
243+
244+
- `-instrument`: Enables profile generation instrumentation
245+
- `--instrumentation-file`: Path where the profile output will be saved
246+
- `--instrumentation-wait-forks`: Ensures the instrumentation continues through forks (important for daemon processes)
247+
248+
## Run the instrumented binary under a feature-specific workload
249+
250+
Start the MySQL instrumented binary in first terminal.
251+
183252
Use a workload generator to stress the binary in a feature-specific way. For example, to simulate **read-only traffic** with sysbench:
184253

185254
```bash
186-
taskset -c 7 sysbench \
255+
taskset -c 7 ./src/sysbench \
187256
--db-driver=mysql \
188257
--mysql-host=127.0.0.1 \
189258
--mysql-db=bench \
@@ -192,16 +261,30 @@ taskset -c 7 sysbench \
192261
--mysql-port=3306 \
193262
--tables=8 \
194263
--table-size=10000 \
264+
--forced-shutdown \
265+
--report-interval=60 \
266+
--rand-type=uniform \
267+
--time=5 \
195268
--threads=1 \
196-
/usr/share/sysbench/oltp_read_only.lua run
269+
--simple-ranges=1 \
270+
--distinct-ranges=1 \
271+
--sum-ranges=1 \
272+
--order-ranges=1 \
273+
--point-selects=10 \
274+
src/lua/oltp_read_only.lua run
197275
```
198276

199277
{{% notice Note %}}
200-
On an 8-core system, cores are numbered 0-7. Adjust the `taskset -c` values as needed for your system. Avoid using the same core for both mysqld and sysbench to reduce contention.
278+
On an 8-core system, cores are numbered 0-7. Adjust the `taskset -c` values as needed for your system. Avoid using the same core for both mysqld and sysbench to reduce contention. You can increase this time (e.g., --time=5 or --time=300) for more statistically meaningful profiling and better .fdata data.
201279
{{% /notice %}}
202280

203281
The `.fdata` file defined in `--instrumentation-file` will be populated with runtime execution data.
204282

283+
After completing each benchmark run (e.g. after sysbench run), you must cleanly shut down the MySQL server and reset the dataset to ensure the next test starts from a consistent state.
284+
```bash
285+
bin/mysqladmin -u root shutdown ; rm -rf /dev/shm/dataset ; cp -R data-orig/ /dev/shm/dataset
286+
```
287+
205288
## Verify the profile was created
206289

207290
After running the workload:

content/learning-paths/servers-and-cloud-computing/bolt-merge/how-to-3.md

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,23 @@ Next, you will collect profile data for a **write-heavy** workload and merge the
1010

1111
## Run Write-Only Workload for Application Binary
1212

13-
Use the same BOLT-instrumented MySQL binary and drive it with a write-only workload to capture `profile-writeonly.fdata`:
13+
Use the same BOLT-instrumented MySQL binary and drive it with a write-only workload to capture `profile-writeonly.fdata`
14+
15+
For this you can reuse the existing instrumented binary, rename .fdata appropriately for read and write workloads or run llvm-bolt with new file target.
16+
```bash
17+
llvm-bolt $HOME/mysql-server/build/bin/mysqld \
18+
-instrument \
19+
-o $HOME/mysql-server/build/bin/mysqldwriteonly.instrumented \
20+
--instrumentation-file=$HOME/mysql-server/build/profile-writeonly.fdata \
21+
--instrumentation-sleep-time=5 \
22+
--instrumentation-no-counters-clear \
23+
--instrumentation-wait-forks \
24+
2>&1 | tee $HOME/mysql-server/bolt-instrumentation-writeonly.log
25+
```
1426

1527
```bash
1628
# On an 8-core system, use available cores (e.g., 7 for sysbench)
17-
taskset -c 7 sysbench \
29+
taskset -c 7 ./src/sysbench \
1830
--db-driver=mysql \
1931
--mysql-host=127.0.0.1 \
2032
--mysql-db=bench \
@@ -23,13 +35,25 @@ taskset -c 7 sysbench \
2335
--mysql-port=3306 \
2436
--tables=8 \
2537
--table-size=10000 \
38+
--forced-shutdown \
39+
--report-interval=60 \
40+
--rand-type=uniform \
41+
--time=5 \
2642
--threads=1 \
27-
/usr/share/sysbench/oltp_write_only.lua run
43+
--simple-ranges=1 \
44+
--distinct-ranges=1 \
45+
--sum-ranges=1 \
46+
--order-ranges=1 \
47+
--point-selects=10 \
48+
src/lua/oltp_write_only.lua run
2849
```
2950

3051
Make sure that the `--instrumentation-file` is set appropriately to save `profile-writeonly.fdata`.
3152

32-
53+
After completing each benchmark run (e.g. after sysbench run), you must cleanly shut down the MySQL server and reset the dataset to ensure the next test starts from a consistent state.
54+
```bash
55+
./build/bin/mysqladmin -u root shutdown ; rm -rf /dev/shm/dataset ; cp -R data-orig/ /dev/shm/dataset
56+
```
3357
### Verify the Second Profile Was Generated
3458

3559
```bash
@@ -72,24 +96,17 @@ ls -lh $HOME/mysql-server/build/profile-merged.fdata
7296
Use LLVM-BOLT to generate the final optimized binary using the merged `.fdata` file:
7397

7498
```bash
75-
llvm-bolt $HOME/mysql-server/build/runtime_output_directory/mysqld \
76-
-instrument \
77-
-o $HOME/mysql-server/build/runtime_output_directory/mysqld.instrumented \
78-
--instrumentation-file=$HOME/mysql-server/build/profile-readonly.fdata \
79-
--instrumentation-sleep-time=5 \
80-
--instrumentation-no-counters-clear \
81-
--instrumentation-wait-forks
82-
83-
llvm-bolt $HOME/mysql-server/build/runtime_output_directory/mysqld \
84-
-o $HOME/mysql-server/build/mysqldreadwrite_merged.bolt_instrumentation \
85-
-data=$HOME/mysql-server/build/prof-instrumentation-readwritemerged.fdata \
99+
llvm-bolt $HOME/mysql-server/build/bin/mysqld \
100+
-o $HOME/mysql-server/build/bin/mysqldreadwrite_merged.bolt_instrumentation \
101+
-data=$HOME/mysql-server/build/profile-merged.fdata \
86102
-reorder-blocks=ext-tsp \
87103
-reorder-functions=hfsort \
88104
-split-functions \
89105
-split-all-cold \
90106
-split-eh \
91107
-dyno-stats \
92-
--print-profile-stats 2>&1 | tee bolt_orig.log
108+
--print-profile-stats \
109+
2>&1 | tee $HOME/mysql-server/build/bolt-readwritemerged-opt.log
93110
```
94111

95112
This command optimizes the binary layout based on the merged workload profile, creating a single binary (`mysqldreadwrite_merged.bolt_instrumentation`) that is optimized across both features.

0 commit comments

Comments
 (0)