MariaDB 字符串相关操作的优化

在我们即将发布的 MariaDB 5.3 版本中,Monty 优化了内部字符串追加代码以提升性能。我使用未打补丁的 MariaDB 5.2 与打过补丁的 MariaDB 5.2 对比,通过 sql-bench 进行了测试,结果显示整体性能提升了约 3%。

Monty 对此补丁的细节描述如下:

优化字符串追加的补丁

在检查 mysql-test-run 用例的跟踪输出时,我注意到存在大量
重新分配(reallocation)调用。这很奇怪,因为 MariaDB/MySQL 的设计
理念是尽可能少地进行 malloc/realloc 操作。系统通常是先计算所需的缓冲区大小,
然后分配一个足够大的缓冲区以满足大多数使用情况。之后还有一些安全调用,
以便在需要时扩展缓冲区。
(Continued from p i=32)

随着时间推移,MySQL 代码中发生的变化是,新的开发者开始使用未预先分配的缓冲区,
并且其中充满了大量的 append calls() 调用,
每次调用都会导致一次新的 realloc() 操作。

我修复了几个最糟糕的情况,使其能够正确地预先分配缓冲区,
对于其他情况,我通过让重新分配过程具有自适应性,进行了一般性修复。
(Continued from p i=38)

核心是将 realloc() 调用替换为以下函数

bool realloc_with_extra(uint32 arg_length)
{
  if (extra_alloc < 4096)
    extra_alloc= extra_alloc*2+128;

  return realloc(arg_length + extra_alloc);
}

在 MySQL 5.3 中,这使得一些测试用例(在调试模式下)的速度提升了
25%。对于优化版本的 MySQL,我们获得了整体
3% 的性能提升。区别在于
在调试构建中,我们对 malloc() 调用进行了很多额外检查,
而更少的 malloc() 调用带来了显著的速度提升。

完整的补丁可以在 MariaDB 5.3 树中通过执行以下命令查看:
bzr log  -p -r monty@askmonty.org-20101108114354-jl61qx8e36gvbzm7

以下是 sql-bench 运行的详细结果。我使用默认设置运行了 MariaDB 5.2.2 上的 sql-bench,并使用了 MyISAM 作为存储引擎。

第 1 列以秒为单位。所有其他列均以相对值表示
于此。1.00 表示相同,较大的数字表示较慢。

1) MariaDB 5.2.2.
2) 打了 Monty 字符串追加优化补丁的 MariaDB 5.2.2。
3) 打了 Monty 字符串追加优化补丁的 MariaDB 5.2.2。
4) 打了 Monty 字符串追加优化补丁的 MariaDB 5.2.2。

每个测试后面的括号中的数字显示了特定测试执行了多少条 SQL 命令。
由于一个测试可能有很多不同的参数,这只能提供一个粗略的
执行情况概览。

我在一个相当快的机器上运行了测试,因此你可以忽略运行时间在 0-3 秒左右的结果。我正在调整测试,使其至少运行 5 秒,以便获得更可靠的结果。

我使用的机器是我们新的基准测试系统“pitbull”,我也曾用它来测试 MyISAM 分段键缓存性能

# OS: Ubuntu 10.10
# Platform: x86_64
# CPU: Two-socket x hexa-core Intel Xeon X5660 @ 2.80GHz. With hyperthreading: 24CPUs
# RAM: 28GB
# Disk(s): 1 x ST3500320NS S-ATA
=================================================================================
Operation                           |         1|         2|         3|         4|
                                    |mysql-Linu|mysql-Linu|mysql-Linu|mysql-Linu|
---------------------------------------------------------------------------------
Relative results per test (First column is in seconds):                         |
---------------------------------------------------------------------------------
ATIS                                |    407.00|     0.980|     0.983|     0.978|
alter-table                         |    112.00|     0.991|     0.955|     0.991|
big-tables                          |    425.00|     0.965|     0.953|     0.958|
connect                             |    403.00|     0.893|     0.963|     0.846|
create                              |    918.00|     0.997|     1.001|     0.971|
insert                              |    536.00|     1.007|     1.034|     1.011|
select                              |    417.00|     0.959|     0.868|     0.986|
wisconsin                           |    408.00|     1.007|     0.983|     0.985|
---------------------------------------------------------------------------------
The results per operation:                                                      |
---------------------------------------------------------------------------------
alter_table_add (992)               |     73.00|     0.973|     0.945|     0.973|
alter_table_drop (496)              |     38.00|     1.026|     0.947|     1.000|
connect (50000)                     |     41.00|     1.024|     1.024|     1.000|
connect+select_1_row (50000)        |     48.00|     1.042|     1.042|     1.021|
connect+select_simple (50000)       |     45.00|     1.022|     1.022|     1.022|
count (100)                         |      3.00|     0.667|     0.667|     0.667|
count_distinct (7000)               |     22.00|     1.000|     1.000|     1.000|
count_distinct_2 (7000)             |     38.00|     1.000|     1.000|     1.000|
count_distinct_big (720)            |     19.00|     1.105|     1.000|     1.053|
count_distinct_group (7000)         |     36.00|     0.667|     0.667|     0.972|
count_distinct_group_on_key (7000)  |     29.00|     1.034|     1.000|     1.034|
count_distinct_group_on_key_parts (7|     33.00|     1.000|     0.697|     0.818|
count_distinct_key_prefix (7000)    |     15.00|     1.000|     0.933|     1.000|
count_group (7000)                  |     33.00|     1.000|     0.606|     1.030|
count_group_on_key_parts (7000)     |     27.00|     1.074|     1.000|     1.037|
count_group_with_order (7000)       |     34.00|     1.000|     0.618|     1.029|
count_on_key (50100)                |     66.00|     0.848|     0.955|     0.955|
create+drop (10000)                 |    450.00|     1.002|     1.007|     0.973|
create_MANY_tables (400)            |     17.00|     1.059|     1.059|     1.059|
create_index (8)                    |      0.00|     1.000|     0.000|     1.000|
create_key+drop (10000)             |    450.00|     0.991|     0.996|     0.967|
create_table (31)                   |      2.00|     0.500|     0.500|     0.500|
delete_all_many_keys (1)            |      5.00|     1.200|     1.200|     1.000|
delete_big (1)                      |      0.00|     0.000|     0.000|     0.000|
delete_big_many_keys (128)          |      5.00|     1.200|     1.200|     1.000|
delete_key (10000)                  |      2.00|     0.500|     0.500|     0.500|
delete_range (12)                   |      1.00|     2.000|     1.000|     1.000|
drop_index (8)                      |      1.00|     0.000|     1.000|     1.000|
drop_table (28)                     |      0.00|     0.000|     0.000|     0.000|
drop_table_when_MANY_tables (400)   |      1.00|     0.000|     0.000|     0.000|
insert (350768)                     |     39.00|     1.103|     1.077|     1.051|
insert_duplicates (100000)          |      9.00|     1.000|     1.444|     1.333|
insert_key (100000)                 |     25.00|     0.960|     1.040|     0.960|
insert_many_fields (140000)         |    112.00|     0.982|     0.982|     0.982|
insert_select_1_key (1)             |      1.00|     1.000|     1.000|     1.000|
insert_select_2_keys (1)            |      0.00|     0.000|     1.000|     1.000|
min_max (60)                        |      1.00|     2.000|     1.000|     2.000|
min_max_on_key (85000)              |     16.00|     1.000|     1.000|     1.000|
multiple_value_insert (100000)      |      1.00|     0.000|     1.000|     1.000|
once_prepared_select (100000)       |     13.00|     1.000|     1.308|     1.231|
order_by_big (10)                   |      5.00|     1.000|     1.200|     1.200|
order_by_big_key (10)               |      6.00|     0.833|     1.000|     0.833|
order_by_big_key2 (10)              |      5.00|     1.000|     1.000|     1.200|
order_by_big_key_desc (10)          |      5.00|     1.200|     1.000|     1.200|
order_by_big_key_diff (10)          |      6.00|     1.000|     0.833|     0.833|
order_by_big_key_prefix (10)        |      5.00|     1.000|     1.200|     1.000|
order_by_key2_diff (500)            |      1.00|     1.000|     1.000|     1.000|
order_by_key_prefix (500)           |      1.00|     1.000|     1.000|     1.000|
order_by_range (500)                |      1.00|     1.000|     0.000|     0.000|
outer_join (10)                     |      5.00|     1.000|     1.200|     1.000|
outer_join_found (10)               |      5.00|     1.000|     1.000|     1.000|
outer_join_not_found (500)          |      4.00|     1.250|     1.000|     1.250|
outer_join_on_key (10)              |      5.00|     1.000|     0.800|     1.000|
prepared_select (100000)            |     22.00|     0.955|     0.955|     0.955|
select_1_row (500000)               |     52.00|     0.750|     0.788|     0.673|
select_1_row_cache (500000)         |     50.00|     0.660|     0.700|     0.660|
select_2_rows (500000)              |     57.00|     0.772|     0.947|     0.684|
select_big (80)                     |      5.00|     1.200|     1.000|     1.200|
select_big_str (50000)              |     14.00|     1.071|     1.071|     1.071|
select_cache (10000)                |     18.00|     1.000|     0.944|     0.944|
select_cache2 (10000)               |     18.00|     0.944|     0.944|     0.944|
select_column+column (500000)       |     53.00|     0.925|     0.830|     0.792|
select_diff_key (500)               |      0.00|     0.000|     0.000|     0.000|
select_distinct (40000)             |    113.00|     1.018|     1.009|     1.009|
select_group (140111)               |    121.00|     1.008|     1.041|     1.000|
select_group_when_MANY_tables (400) |      0.00|     0.000|     0.000|     0.000|
select_join (5000)                  |     22.00|     1.000|     1.000|     1.000|
select_key (200000)                 |     43.00|     1.000|     0.977|     0.953|
select_key2 (200000)                |     46.00|     0.978|     0.957|     0.957|
select_key2_return_key (200000)     |     44.00|     1.000|     0.977|     0.955|
select_key2_return_prim (200000)    |     46.00|     0.978|     0.935|     0.935|
select_key_prefix (200000)          |     46.00|     1.022|     0.957|     0.957|
select_key_prefix_join (5000)       |    131.00|     0.908|     0.893|     0.916|
select_key_return_key (200000)      |     43.00|     0.953|     0.953|     0.953|
select_many_fields (140000)         |    313.00|     0.958|     0.942|     0.949|
select_range (410)                  |     22.00|     0.955|     0.955|     1.000|
select_range_key2 (25010)           |      5.00|     1.000|     1.200|     1.000|
select_range_prefix (25010)         |      6.00|     1.000|     1.000|     1.000|
select_simple (500000)              |     22.00|     1.000|     1.318|     0.955|
select_simple_cache (500000)        |     21.00|     0.952|     1.524|     0.952|
select_simple_join (25000)          |     22.00|     1.045|     1.045|     1.000|
update_big (10)                     |      4.00|     1.000|     1.000|     1.000|
update_of_key (50000)               |      6.00|     1.167|     1.333|     1.333|
update_of_key_big (501)             |      3.00|     1.000|     1.000|     0.667|
update_of_primary_key_many_keys (256|      3.00|     0.667|     1.000|     0.667|
update_with_key (300000)            |     30.00|     1.133|     1.333|     1.333|
update_with_key_prefix (100000)     |     10.00|     1.100|     1.400|     1.400|
wisc_benchmark (50014)              |    403.00|     1.010|     0.988|     0.988|
---------------------------------------------------------------------------------
TOTALS                              |   3619.00|     0.978|     0.975|     0.966|
=================================================================================