侵权投诉
订阅
纠错
加入自媒体

简析:NVM WAL BUFFER的email list

2021-03-05 10:12
yzsDBA
关注

本文介绍NVM WAL BUFFER的email list,详细了解开发者对此的讨论,以此深入了解机制。

1、Heikki

使用mmap()/msync()映射WAL文件,替代WAL buffer。如果读memory-mapped文件有IO错误时,进程会通过SIGBUS杀掉。

重新阅读了[1][2],使用WAL段文件映射到内存作为WAL BUFFER,依赖于WAL文件是否放在PM上切换CPU指令或者msync()用于持久化WAL记录。

听起来挺合理,但是我没测试过。我会尝试与NVM WAL BUFFER进行比对测试。现在,有点担心对于每个段文件mmap/munmap带来的消耗。

同时提到内存映射IO的SIGBUS问题,从坏的内存块读取时会有这个问题,向这个块[3]写时也有这个问题。未来会处理这个问题。

[1]https://www.postgresql.org/message-id/83eafbfd-d9c5-6623-2423-7cab1be3888c%40iki.fi

[2]https://www.postgresql.org/message-id/2aec6e2a-6a32-0c39-e4e2-aad854543aa8%40iki.fi

[3] https://pmem.io/2018/11/26/bad-blocks.htm

https://www.postgresql.org/message-id/2aec6e2a-6a32-0c39-e4e2-aad854543aa8%40iki.fi

2、mmap/munmap带来的消耗

mmap/munmap每个WAL段文件的消耗与write一个block的消耗谁更大。mmap比read消耗大,但是减小系统调用又可以使mmap更具优势。这只是猜测,并不知道mmap真实消耗是多少。

我有一个不同想法,当重用一个段文件时,会一次写所有整个页,段文件的即使没有读取过,也会被重写。但是使用mmap时就不会有这样的行为了。只要想mapped页写一个字节,老内容就会被加载到内存。VM页在该点设置读写后,系统不知道将要写整个页。读取回收文件的老内容显然代价太过糟糕。

当修改mapped区和write()时,对于write-back行为是否有所不同。不管哪种方式,同一个文件同一个页面都会被写脏,但内核可能对何时写回磁盘有不同行为,这对性能影响很大。

这个问题可以分为两类:性能和一致性。程序的作者同样忧虑这些问题,但是也没有一个很好的答案。作者认为同一个文件被多个后端进程调用mmap(flags | MAP_SHARED)对于PM和非PM设备都是保持一致性的,但是还没找到任何如规范文件来证明。

作者在同一个mmaped文件上做了一个小程序,调用memcpy和msync,并行的地址范围不同,没发现损坏的数据。但这也无妨确保一致性,如果有损坏,作者会放弃...

作者会测试Heikki所说的使用mmap和munmap映射每个段文件,来看是否合理。

Mmap/munmap可伸缩性确实很差,但是不认为会影响我们,因为PG不是多线程。

针对mmap/munmap,这样做有很多改进。即使现在,在快速存储方面,使用open_datasync会更快(至少在O_DIRECT上)。WAL扩展是一个挑战性问题。不修改IO方式,有很多地方可以优化以提升性能:

1)将WALWriteLock分成两个锁:一个用于写,一个用于flush wal。现在,一个会话进行flush一个wal时,其他会话不能write wal,即使该wal位于其他段文件。没有必要这样做。

2)XLogFlush()中刷写WAL时不要将刷写请求的大小增加到最大(cf "try to write/flush later additions to XLOG as well" in XLogFlush()),可以显著减小OLTP负载。在SATA盘上有意义,但是对于SSD来说影响较小。写的多,持久锁时间就更长,增加了事务提交的延迟,组织更多的WAL写。

3)应该立即将所有的XLOG页的writes刷写会操作系统。现在,在OLTP负载中IO永远不会再commit之前出现,也就是说在XLogWrite()和commit之间的完全是在浪费时间。

做了这几点,猜想能有2-3倍的性能提升。但是不得不从根本上改变WAL write的IO方式。使用异步IO,可以像18k一样每秒持久化8kb的write。在我笔记本上,写4k,就是22k。

当然这和PG的wal flush没可比性,因为WAL 经常会重复写最后一个block。但不会记录到组提交里。

NVM WAL BUFFER的path:

0001-Preallocate-more-WAL-segments.patch (3K) Download Attachment

0002-Use-WAL-segments-as-WAL-buffers.patch(40K) Download Attachment

0003-Lazy-unmap-WAL-segments.patch (2K) Download Attachment

0004-Speculative-map-WAL-segments.patch (1K) Download Attachment

0005-Allocate-WAL-segments-to-utilize-hugepage.patch(1K) Download Attachment

3、是否可以模拟PM用于测试

通过“memmap=nnG!ssG”内核参数使用DRAM模拟PM。参考[1]和[2]了解详细模拟步骤。如果不起作用,检查PM和DAX的内核配置选项,比如CONFIG_FOOBAR,是否配置正确。

[1] How to Emulate Persistent Memory Using Dynamic Random-access Memory (DRAM)

https://software.intel.com/en-us/articles/how-to-emulate-persistent-memory-on-an-intel-architecture-server

[2] how_to_choose_the_correct_memmap_kernel_parameter_for_pmem_on_your_system

https://nvdimm.wiki.kernel.org/how_to_choose_the_correct_memmap_kernel_parameter_for_pmem_on_your_system

[3] Persistent Memory Wiki

https://nvdimm.wiki.kernel.org/

4、对于mmap WAL性能的测试

针对PG12分别进行修改。通过pgbench进行压测。SSD上存储WAL,map后的结果比原生PG性能差很多。VTune显示CopyXLogRecordToWAL的memcpy动作消耗的CPU时间比原生的大的多。使用NVDIMM-N,ext4-dax存储WAL,结果差不多,XLogInsert() 和XLogFlush()消耗的时间mmap和NVM WAL BUFFER的差不多。在PM上通过mmap WAL段文件作为WAL BUFFER是个很好的尝试。但是该path可能还有bug,并不能说性能提升或者下降。

5、作者的NVM WAL BUFFER测试

通过pgbench,指定不同的-c/--client和-j/--job,数据量规模因子s=50或者1000.结果如下:

Results (s=50) :

==============

         Throughput [10^3 TPS]  Average latency [ms]

( c, j)    before  after      before  after

-------  ---------------------  ---------------------

( 8, 8)  35.7    37.1 (+3.9%)   0.224   0.216 (-3.6%)

(18,18)  70.9    74.7 (+5.3%)   0.254   0.241 (-5.1%)

(36,18)  76.0    80.8 (+6.3%)   0.473   0.446 (-5.7%)

(54,18)  75.5    81.8 (+8.3%)   0.715   0.660 (-7.7%)

Results (s=1000)

================

         Throughput [10^3 TPS]  Average latency [ms]

( c, j)  before  after          before  after

-------  ---------------------  ---------------------

( 8, 8)  37.4    40.1 (+7.3%)   0.214   0.199 (-7.0%)

(18,18)  79.3    86.7 (+9.3%)   0.227   0.208 (-8.4%)

(36,18)  87.2    95.5 (+9.5%)   0.413   0.377 (-8.7%)

(54,18)  86.8    94.8 (+9.3%)   0.622   0.569 (-8.5%)

每个规模因子下,负载和延迟都有所改进。负载在(c,j)=(36,18)下TPS最高。S=1000案例下,提升百分比较大。规模因子大,对于同表和索引的竞争就小些,也就是加锁和解锁的操作较少。这种情况下WAL对性能更重要。

条件:

1)使用一个物理server,2个numa节点:PG绑定到node 0,pgbench到node 1,每个节点18个core,192GB的DRAM

2)PGDATA在nvme ssd上,pg_wal在交互6-in-1的NVDIMM-N上:都安装在server端,node 0,都用ext4,NVDIMM-N被mounted时有“-o dax”

3)新增nvwal_path和nvwal_size参数到postgresql.conf中

步骤:

对每个(c,j)都做三次,然后取平均值:

(1) Run initdb with proper -D and -X options; and also give --nvwal-path and --nvwal-size options after patch

(2) Start postgres and create a database for pgbench tables

(3) Run "pgbench -i -s ___" to create tables (s = 50 or 1000)

(4) Stop postgres, remount filesystems, and start postgres again

(5) Execute pg_prewarm extension for all the four pgbench tables

(6) Run pgbench during 30 minutes

pgbench command line

====================

$ pgbench -h /tmp -p 5432 -U username -r -M prepared -T 1800 -c ___ -j ___ dbname

I gave no -b option to use the built-in "TPC-B (sort-of)" query.

软件

========

- Distro: Ubuntu 18.04

- Kernel: Linux 5.4 (vanilla kernel)

- C Compiler: gcc 7.4.0

- PMDK: 1.7

- PostgreSQL: d677550 (master on Mar 3, 2020)

硬件

========

- System: HPE ProLiant DL380 Gen10

- CPU: Intel Xeon Gold 6154 (Skylake) x 2sockets

- DRAM: DDR4 2666MHz {32GiB/ch x 6ch}/socket x 2sockets

- NVDIMM-N: DDR4 2666MHz {16GiB/ch x 6ch}/socket x 2sockets

- NVMe SSD: Intel Optane DC P4800X Series SSDPED1K750GA

Patch

v2-0001-Support-GUCs-for-external-WAL-buffer.patch(36K) Download Attachment

v2-0002-Non-volatile-WAL-buffer.patch (53K) Download Attachment

v2-0003-README-for-non-volatile-WAL-buffer.patch(7K) Download Attachment

nvwal-performance-s50.png (39K) Download Attachment

nvwal-performance-s1000.png(40K)Download Attachmentpostgresql.conf (1K) Download Attachment

6、增加支持流复制

v4-0001-Support-GUCs-for-external-WAL-buffer.patch (42K) Download Attachment

v4-0002-Non-volatile-WAL-buffer.patch (73K) Download Attachment

v4-0003-walreceiver-supports-non-volatile-WAL-buffer.patch (7K) Download Attachment

v4-0004-pg_basebackup-supports-non-volatile-WAL-buffer.patch (25K) Download Attachment

v4-0005-README-for-non-volatile-WAL-buffer.patch (9K) Download Attachment

7、其他人对NVM WAL BUFFER测试

数据文件放到nvme ssd,WAL放到PM。使用下面两种方式存储WAL文件:

1)NVM WAL BUFFER的分支,利用libpmem

2)通过文件系统接口访问P,就是说将PM当做传统的块设备。都是APP DIRECT方式使用PM。

进行了两种insert场景:

1)插入小记录,记录长度为24字节

2)插入大记录,记录长度328字节

初衷是看下场景2)对于WAL写密集下性能提升多大,但是发现场景1)NVM WAL BUFFER和原生PG相比有大概5%的性能提升,但是在2)有大概20%的性能衰减。

分析后,XlogFlush函数可以通过NVM WAL BUFFER提升,但是会影响CopyXlogRecordToWAL的性能。可能和PM比DRAM的memcpy延迟高有关。下面是测试结果:

Scenario A (length of record to be inserted: 24 bytes per record):

==============================

                                                                              NVWAL                           SoAD

------------------------------------              -------                          -------

Througput (10^3 TPS)                                              310.5                             296.0

CPU Time % of CopyXlogRecordToWAL                    0.4                                 0.2

CPU Time % of XLogInsertRecord                              1.5                                 0.8

CPU Time % of XLogFlush                                          2.1                                 9.6

Scenario B (length of record to be inserted: 328 bytes per record):

==============================

                                                                              NVWAL                           SoAD

------------------------------------              -------                          -------

Througput (10^3 TPS)                                              13.0                               16.9

CPU Time % of CopyXlogRecordToWAL                    3.0                                 1.6

CPU Time % of XLogInsertRecord                              23.0                               16.4

CPU Time % of XLogFlush                                          2.3                                 5.9

8、作者对于328字节性能衰减的回复

对于328字节,作者测试没有性能衰减,认为环境及安装步骤等可能不一样。

结果显示NVM WAL BUFFER比原始有更好性能:

步骤

在同一个机器上跑PG server和pgbench,分别绑定到不同的2个numa节点。Server端的numa节点用于PM和PCI SSD:

01) 创建PMEM namespace (sudo ndctl create-namespace -f -t pmem -m fsdax -M dev -e namespace0.0)

02) 在PM上做ext4文件系统并以dax方式mount(sudo mkfs.ext4 -q -F /dev/pmem0 ; sudo mount -o dax /dev/pmem0 /mnt/pmem0)

03) PCIE SSD也是ext4文件系统,正常mount(sudo mkfs.ext4 -q -F /dev/nvme0n1 ; sudo mount /dev/nvme0n1 /mnt/nvme0n1)

04) /mnt/pmem0/pg_wal 作为WAL目录

05) /mnt/nvme0n1/pgdata PGDATA目录

06) 执行initdb初始化 (initdb --locale=C --encoding=UTF8 -X /mnt/pmem0/pg_wal ...)

   - Also give -P /mnt/pmem0/pg_wal/nvwal -Q 81920 in the case of Non-volatile WAL buffer

07) 在附件的postgresql.conf中删除nvmwal_*对于原始PG测试

08) PG server绑定到NUMA node 0 (numactl -N 0 -m 0 -- pg_ctl -l pg.log start)

09) 创建database (createdb --locale=C --encoding=UTF8)

10) 使用pgbench 初始化t,s=50 (pgbench -i -s 50)

11) ALTER TABLE pgbench_history ALTER filler TYPE character(300);)

   -使表行大小为328 bytes

12) pg_ctl -l pg.log -m smart stop

13) 重新mount PMEM 和 PCIe SSD

14) numactl -N 0 -m 0 -- pg_ctl -l pg.log start

15) 执行 pg_prewarm 预热表 pgbench_* tables

16) 执行pgbench on NUMA node 1 30分钟(numactl -N 1 -m 1 -- pgbench -r -M prepared -T 1800 -c __ -j __)

- 执行默认的 tpcb-like事务

执行3次并取平均值。环境变量:

export PGHOST=/tmp

export PGPORT=5432

export PGDATABASE="$USER"

export PGUSER="$USER"

export PGDATA=/mnt/nvme0n1/pgdata

环境:

- System: HPE ProLiant DL380 Gen10

- CPU: Intel Xeon Gold 6240M x2 sockets (18 cores per socket; HT disabled by BIOS)

- DRAM: DDR4 2933MHz 192GiB/socket x2 sockets (32 GiB per channel x 6 channels per socket)

- Optane PMem: Apache Pass, AppDirect Mode, DDR4 2666MHz 1.5TiB/socket x2 sockets (256 GiB per channel x 6 channels per socket; interleaving enabled)

- PCIe SSD: DC P4800X Series SSDPED1K750GA

- Distro: Ubuntu 20.04.1

- C compiler: gcc 9.3.0

- libc: glibc 2.31

- Linux kernel: 5.7 (vanilla)

- Filesystem: ext4 (DAX enabled when using Optane PMem)

- PMDK: 1.9

- PostgreSQL (Original): 14devel (200f610: Jul 26, 2020)

- PostgreSQL (Non-volatile WAL buffer): 14devel (200f610: Jul 26, 2020) + non-volatile WAL buffer patchset v4

作者按照Gang的环境配置,得到原始PG比NVM WAL BUFFER性能好的结果。需要进一步分析。NVM WAL BUFFER的XLogInsert花费的时间较长。这个拖累了XLogFlush带来的提升,整体上性能衰减了。VTune显示NVM WAL BUFFER的XLogInsert => XLogInsertRecord => CopyXLogRecordsToWAL =>中memcpy花费的时间较长,XLogFlush时间较短。整体结果和Gang一致。PM上的WAL BUFFER相对于DRAM来说,memcpy WAL记录时间长,因为现阶段PM延迟比DRAM大。作为回报,NVM WAL BUFFER减小了让记录命中设备的时间,因为不需要将他们从缓冲区写到其他地方,只需要将CPU cache中内容持久化到NVM。会继续跟踪。


声明: 本文由入驻维科号的作者撰写,观点仅代表作者本人,不代表OFweek立场。如有侵权或其他问题,请联系举报。

发表评论

0条评论,0人参与

请输入评论内容...

请输入评论/评论长度6~500个字

您提交的评论过于频繁,请输入验证码继续

暂无评论

暂无评论

    电子工程 猎头职位 更多
    扫码关注公众号
    OFweek电子工程网
    获取更多精彩内容
    文章纠错
    x
    *文字标题:
    *纠错内容:
    联系邮箱:
    *验 证 码:

    粤公网安备 44030502002758号