mmap映射物理内存之一cache与lock

发布于:2025-06-29 ⋅ 阅读:(14) ⋅ 点赞:(0)

         

目录

单板内存性能

cache与否

  map_locked参数与mlock

    malloc申请内存

mmap映射保留内存

 开关cache的耗时对比

总结


     

     本文介绍通过mmap映射预留的内存,预留内存通过cmdline中增加mem参数来实现。

    测试环境为飞腾D2000。

单板内存性能

以mbw,单进程测试性能带宽,此测试占用完整一个CPU核,但内存带宽并没有压满,仅仅测试单个CPU读写内存的带宽,以此为基准,对比查看应用在使用内存时的性能。

 ./mbw -q -n 10 5000

Method: MEMCPY  3624.776 MiB/s
 Method: DUMB  1052.553 MiB/s
Method: MCBLOCK 3614.032 MiB/s

  即,3.6MB/ms的拷贝速率。

cache与否

通过mmap接口映射一段内存,映射后的地址是带cache,还是不带cache呢

走读代码 : kernel\drivers\char\mem.c

mmap_mem->phys_mem_access_prot->uncached_access

这里可以看到在内核以外的地址,例如通过cmdline中增加mem限制以上的内存,通过mmap映射后,默认是关闭cache的

而对于巨页等内核可见的内存,通过mmap映射则cache为打开。比如DPDK使用的 mmap映射。

/* map the segment, and populate page tables,
		 * the kernel fills this segment with zeros. we don't care where
		 * this gets mapped - we already have contiguous memory areas
		 * ready for us to map into.
		 */
		virtaddr = mmap(NULL, hugepage_sz, PROT_READ | PROT_WRITE,
				MAP_SHARED | MAP_POPULATE, fd, 0);
		if (virtaddr == MAP_FAILED) {
			EAL_LOG(DEBUG, "%s(): mmap failed: %s", __func__,
					strerror(errno));
			close(fd);
			goto out;
		}

  map_locked参数与mlock

    

    通常的内存使用如上图,进程创建时建立页表,以映射虚拟地址和物理地址的关系,例如此时进程1占用了此块内存。

   而当进程1,不活跃时,其部分数据内存被认为不活跃,则会被swap磁盘中,并且对应页表会设置为缺页状态,也就是无实际对应的物理内存。

   而进程2此时创建,建立页表,将自己的虚拟地址映射到了原先进程1的内存。

    mlock 可以使进程1一直占用此内存,减少了swap耗时和缺页处理的耗时。

  

    malloc申请内存

   1)   我们用malloc申请两段内存,进行数据拷贝。      

src=(unsigned int *)malloc(0x2000000);
        dst=(unsigned int *)malloc(0x2000000);

拷贝耗时

malloc Read back: 0x0, copy (32)M 14173.000000 us

 2.28MB/ms

2) mlock dst内存

   if (mlock(dst, copy_size) == 0) {
    printf("Memory locked malloc successfully\n");
	} else {
	    perror("mlock malloc failed");
	} 

此时拷贝耗时

malloc Read back: 0x0, copy (32)M 7110.000000 us

4.56MB/ms

拷贝方法 速率 耗时(32M数据)
mbw测试 3.6MB/ms
memcpy  2.28MB/ms 14MS
memcpy+mlock dst地址 4.56MB/ms 7MS

mlock确认生效

通过查看进程status,可以看到进程的确lock了 32MB的内存。

cat /proc/2877/status
Name:   mmapresv

VmSize:   198540 kB
VmLck:     32772 kB

mmap映射保留内存

if (mlock(mem, reserved_size) == 0) {
    printf("Memory locked successfully\n");
	} else {
	    perror("mlock failed");
	}  

 mem地址是通过mmap映射保留内存的虚拟地址,虽然上述mlock执行成功,但实际查看进程的lock内存,值为0,也就是说实际上lock功能并没有对此时mmap应用场景生效。

cat /proc/2830/status
Name:   mmapresv

VmSize:   198540 kB
VmLck:         0 kB

 开关cache的耗时对比

  mmap将保留的物理地址映射为带cache与不带cache。进行拷贝测试

 关cache

Read back: 0x0, copy (32)M 364115.000000 us

开cache

Read back: 0x0, copy (32)M 17313.000000 us

开cache,并且clean cache

Read back: 0x0, copy (32)M 43951.000000 us

 32M 数据拷贝如下. 关cache即 源和目的都关;开则源和目的都开。

关cache 364MS 90KB/ms
开cache 17MS 1.88MB/ms
开cache,且clean cache 44MS 745KB

总结

    期望通过mmap实现对保留物理内存的映射,并完成数据的拷贝。但是简单映射性能比较差。

    1)关闭cache后,再让CPU读写,速率只有100MB/s左右。这种方式虽然和外设DMA打交道时简单,但是到CPU 读写数据时,速率太慢。

因素 影响
失去 Cache 加速 每次读写直接访问内存(DRAM),延迟从 ~10ns(L1 Cache)升至 ~100ns
总线带宽利用率低 无预取(Prefetch)和突发传输(Burst),总线效率下降
流水线停滞 CPU 无法并行执行指令(需等待内存读写完成)
ARM 架构限制 AArch64 的普通加载/存储指令(如 LDR/STR)在 Non-Cacheable 模式下性能极低

 理论带宽对比

模式 预期带宽(Cortex-A72 示例) 实测典型值
With Cache 10-20 GB/s 2000-5000 MB/s
No Cache 1-5% of peak 50-200 MB/s

 # 使用 perf 统计缓存命中率

perf stat -e cache-misses,cache-references,L1-dcache-load-misses ./your_program

1,000,000 cache-misses      # 缓存未命中率接近 100%

   2)开cache映射

   主要两个问题:

    1) 不能被mlock 锁定成功。导致拷贝优化不上来。

     2) cache在用户态的clean与invalid操作。


网站公告

今日签到

点亮在社区的每一天
去签到