持久内存快速编程手册 (Part 4 of 7)

libpmemblk

libpmemblk 是用于管理固定大小数据块阵列的 C 库。它提供故障安全接口,以通过基于缓冲区的函数更新数据块。libpmemblk 仅用于需要简单固定数据块阵列,且不需要直接字节级访问数据块的情况。所以libpmemblk的接口简单且非常直接。在我们的示例中,主要使用的接口包括:
1.pbp = pmemblk_create(filename, ELEMENT_SIZE, POOL_SIZE, 0666);
2.pbp = pmemblk_open(filename, ELEMENT_SIZE);
3.nelements = pmemblk_nblock(pbp);
4.pmemblk_write(pbp, content, req_id)
5.pmemblk_read(pbp, buf, req_id)
所以这个库非常适合我们全文讨论的使用持久内存作为页缓存的需求。其实现示例 3所示:
示例 3 libpmemblk实现持久化页缓存

#include <fcntl.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <libpmemblk.h>
#include <iostream>
#include <chrono>
#include <cassert>


/* size of the pmemblk pool -- 100 GB */
#define POOL_SIZE ((uint64_t)((1<< 30)*100UL))

/* size of each element in the pmem pool */
#define ELEMENT_SIZE 4096

// pmem block pool
PMEMblkpool *pbp;
size_t nelements;

int cbs_init(const char * filename)
{
  /* create the pmemblk pool or open it if it already exists */
  pbp = pmemblk_create(filename, ELEMENT_SIZE, POOL_SIZE, 0666);

  if (pbp == NULL)
    pbp = pmemblk_open(filename, ELEMENT_SIZE);

  if (pbp == NULL) {
    perror(filename);
    return -1;
  }

  /* how many elements fit into the file? */
  nelements = pmemblk_nblock(pbp);
  printf("file holds %zu elements", nelements);  
  return 0;
}

int write_req(uint64_t req_id, unsigned char * content) {
  assert(req_id < nelements);
  if (pmemblk_write(pbp, content, req_id) < 0) {
    perror("pmemblk_write");
    return -1;
  }
  
  return 0;
}

void * read_req(uint64_t req_id, unsigned char * buf) {
  assert(req_id<nelements);
  /* read the block at index 10 (reads as zeros initially) */
  if (pmemblk_read(pbp, buf, req_id) < 0) {
    perror("pmemblk_read");
    return NULL;
  }
  return buf;
}

#define WRITE_COUNT 100000
#define OVERWRITE_COUNT 10000
int main() 
{
  // calculate the time
  unsigned char * read_content;
  unsigned char * page_content=(unsigned char *)malloc(4096);
  uint64_t i=0;
  auto start=std::chrono::steady_clock::now();
  auto stop=std::chrono::steady_clock::now();
  std::chrono::duration<double> diff=stop-start;

  memset(page_content,0xab,4096);
  
  start=std::chrono::steady_clock::now();
  cbs_init("/mnt/pmem0/cbs_pmblk");
  stop=std::chrono::steady_clock::now();
  diff=stop-start;
  std::cout<<"cbs_init time"<<diff.count()<<std::endl; 
  
  //std::cout<<"cached page count"<<get_cached_count()<<std::endl;
  start = std::chrono::steady_clock::now();
  for(i=0;i<WRITE_COUNT;i++) {
    write_req(i,page_content);
  }
  stop=std::chrono::steady_clock::now();
  diff=stop-start;
  std::cout<<"write_req time"<<diff.count()/WRITE_COUNT<<std::endl;

  memset(page_content,0xcd,4096);
  start = std::chrono::steady_clock::now();
  for(i=0;i<OVERWRITE_COUNT;i++) {
    write_req(i,page_content);
  }
  stop=std::chrono::steady_clock::now();
  diff=stop-start;
  std::cout<<"overwrite write_req update take time "<< diff.count()/OVERWRITE_COUNT<<std::endl;

  start = std::chrono::steady_clock::now(); 
  for(i=0;i<OVERWRITE_COUNT;i++) {
    read_content=( unsigned char *)read_req(i,page_content);
  }
  stop=std::chrono::steady_clock::now();
  diff=stop-start;
  std::cout<<"overwrite read_req take time "<<diff.count()/OVERWRITE_COUNT<<std::endl;
  printf("the page should fill with paten 0xcd, 0x%x\n", read_content[0]);

  start = std::chrono::steady_clock::now();
  for(i=OVERWRITE_COUNT;i<WRITE_COUNT;i++) {
    read_content=( unsigned char *)read_req(i,page_content);
  }
  stop=std::chrono::steady_clock::now();
  diff=stop-start;
  std::cout<<"overwrite->write count read_req take time "<<diff.count()/(WRITE_COUNT-OVERWRITE_COUNT)<<std::endl;
  printf("the page should fill with patern 0xab, 0x%x\n", read_content[0]);

  pmemblk_close(pbp);
  return 0;
}

编译“g++ cbs_req_pmemblk.cpp -o cbs_req_pmemblk -lpmemblk -O2”, 然后跑“taskset -c 2 ./cbs_req_pmemblk” ,第一次写4k是4.2us,第二次写是3us,读是1.35us.

~ taskset -c 2 ./cbs_req_pmemblk
file holds 26188559 elementscbs_init time0.0573344
write_req time4.19133e-06
overwrite write_req update take time 2.99101e-06
overwrite read_req take time 1.2958e-06
the page should fill with paten 0xcd, 0xcd
overwrite->write count read_req take time 1.348e-06
the page should fill with patern 0xab, 0xab~ taskset -c 2 ./cbs_req_pmemblk
file holds 26188559 elementscbs_init time0.00895083
write_req time2.99173e-06
overwrite write_req update take time 2.92603e-06
overwrite read_req take time 1.27759e-06
the page should fill with paten 0xcd, 0xcd
overwrite->write count read_req take time 1.34219e-06
the page should fill with patern 0xab, 0xab

关注英特尔边缘计算社区,表示您确认您已年满 18 岁,并同意向英特尔分享个人信息,以便通过电子邮件和电话随时了解最新英特尔技术和行业趋势。您可以随时取消订阅。英特尔网站和通信内容遵守我们的隐私声明使用条款

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值