天天看點

PMDKdefine MOVNT_THRESHOLD 256

PMDK is popular nowadays. To practice, please start from http://pmem.io

.

在 src/examples/libpmem/ 目錄下有三個簡單的例子:full\_copy.c、manpage.c、simple\_copy.c。我們選擇 full\_copy.c 做測試,并在其基礎上修改為 copy\_mem.c。

在得到的測試資料中可以發現幾個明顯的拐點,例如:

  1. devdax 模式下,每次 flush 32 位元組比 64 位元組要慢很多。因為 cache line 的大小是 64 位元組。
  2. devdax 模式下,每次 flush 128 位元組也比 256 位元組要慢很多。 推測是 PMEM\_MOVNT\_THRESHOLD 預設設定為 256 導緻的,256 位元組以上的資料将采用 Cache of Non-temporal Data 的寫 Cache 模式。

    $ cat src/libpmem/x86_64/init.c

    define MOVNT_THRESHOLD 256

    size_t Movnt_threshold = MOVNT_THRESHOLD;
  3. xfs 模式下,每次 flush 2048 位元組也比 4096 位元組要慢很多。因為 xfs 的塊大小(等同核心的頁面大小)是 4096 位元組。
  4. fsdax 模式下,每次 flush 128 位元組也比 256 位元組要慢很多。因為 fsdax 模式下,首次缺頁都會要先寫零并持久化。
  5. fsdax 模式比 devdax 模式大約會慢 2-3 倍。除了缺頁寫零之外還有哪些額外操作?

Perf 的輸出中可以明顯看到 fsdax 模式下有很多 memcpy\_flushcache 的調用。主要是走/不走 cache 的差别。

fsdax
    43.25%  copy_mem  libpmem.so.1.0.0  [.] memmove_movnt_sse2_clwb
    39.21%  copy_mem  [kernel.vmlinux]  [k] memcpy_flushcache

devdax
    86.16%  copy_mem  libpmem.so.1.0.0  [.] memmove_movnt_sse2_clwb
     7.14%  copy_mem  libpmem.so.1.0.0  [.] memmove_nodrain_sse2_clwb
           

那麼為什麼 fsdax 會有很多 memcpy\_flushcache 的調用,而 devdax 沒有?從 perf 獲得的調用棧:

__libc_start_main
main
memmove_movnt_sse2_clwb
page_fault
do_page_fault
__do_page_fault
handle_mm_fault
__handle_mm_fault
__xfs_filemap_fault
dax_iomap_fault
xfs_file_iomap_begin
xfs_iomap_write_direct
xfs_bmapi_write
xfs_bmapi_convert_unwritten
blkdev_issue_zeroout
submit_bio_wait
submit_bio
generic_make_request
pmem_make_request
pmem_do_bvec
write_pmem
memcpy_flushcache
           

那麼 clwb 函數是怎麼定義的?查 libpmem 代碼即可。

[root@localhost libpmem]# grep -rwIn memmove_movnt_sse2_clwb /home/test/pmdk-sandbox/src
/home/test/pmdk-sandbox/src/libpmem/x86_64/memcpy/memcpy_nt_sse2_clwb.c:34:#define EXPORTED_SYMBOL memmove_movnt_sse2_clwb
/home/test/pmdk-sandbox/src/libpmem/x86_64/memcpy_memset.h:83:void memmove_movnt_sse2_clwb(char *dest, const char *src, size_t len);
           

注意上面那個 #define。找到對應的代碼:src/libpmem/x86\_64/memcpy/memcpy\_nt\_sse2.h

void
EXPORTED_SYMBOL(char *dest, const char *src, size_t len)
{
    if ((uintptr_t)dest - (uintptr_t)src >= len)
    memmove_movnt_sse_fw(dest, src, len);
    else
    memmove_movnt_sse_bw(dest, src, len);

    maybe_barrier();
}
           

Since PMDK is in active development, the best practice is to read the code and follow the changes.

As for CLFLUSH、CLFLUSHOPT、CLWB's difference, read the code and refer to

http://research.cs.wisc.edu/sonar/tutorial/03-hardware.pdf

links to:

https://zedware.github.io

繼續閱讀