大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是内存读写正确性压力测试程序memtester

在嵌入式系统中,内存(RAM)的重要性不言而喻,系统性能及稳定性都与内存息息相关。关于内存性能有很多个不同指标,其中最基础的指标便是访问可靠性(即读写的正确性),只有稳定可靠的内存访问才能确保系统正常运行。很多时候简单地内存读写测试并不能发现隐藏的问题,因此我们需要一个完备的内存访问压力测试程序,今天痞子衡就和大家详细聊一聊memtester。

一、内存性能测试程序集

在讲memtester之前,痞子衡先给大家科普一下Linux系统下常用的内存性能测试工具,它们分别是mbw、memtester、lmbench、sysbench。这几个测试工具(程序)各有侧重点:

内存带宽测试工具            --mbw;
内存压力测试工具            --memtester;
内存综合性能测试工具        --lmbench;
内存申请与读写速度测试工具   --sysbench;

二、memtester程序

memtester是Simon Kirby在1999年编写的测试程序(v1版),后来由Charles Cazabon一直维护更新(v2及之后版本),主要面向Unix-like系统,官方主页上介绍的是“A userspace utility for testing the memory subsystem for faults.”,其实就是为了测试内存(主要DDR)的读写访问可靠性(仅正确性,与速度性能无关),这是验证板级硬件设备必不可少的一项测试。

整个memtester测试的视角就是从用户的角度来看的,从用户角度设立不同的测试场景即测试用例,然后针对性地进行功能测试,注意是从系统级来测试,也就是说关注的不单单是内存颗粒了,还有系统板级的连线、IO性能、PCB等等相关的因素,在这些因素的影响下,内存是否还能正常工作。

2.1 获取程序

memtester程序的最新版本是4.5.0,早期的v1/v2/v3版本目前下载不到了,2012年Charles Cazabon重写了程序并发布了全新v4.0.0,此后一直不定期更新,v4.x也是当前最流行的版本。

核心程序下载:http://pyropus.ca/software/memtester/

核心程序包下载后,在\memtester-4.5.0\下可找到源代码。详细源文件目录如下:

\memtester-4.5.0\memtester.h\memtester.c        --主程序入口\sizes.h            --关于系统位数(32/64bit)的一些定义\types.h            --所用数据类型的定义\tests.h\tests.c            --测试算法子程序

如果是移植到ARM Cortex-M平台下裸系统运行,一般只需要简单修改memtester.c文件即可,其他源文件就是一些头文件包含方面的改动,memtester本身并没有太多移植工作,其源码本是用作在Unix-like系统上运行的,而在嵌入式系统里运行仅需要把一些跟系统平台相关的代码删除即可,此外就是打印函数的实现。

2.2 配置参数

memtester源码里的配置选项主要是如下五个宏:

/* 如下需用户自定义 */
ULONG_MAX             -- 确定系统是32bit还是64bit
TEST_NARROW_WRITES    -- 确定是否要包含8/16 bit写测试/* 如下借助linux头文件 */
_SC_VERSION           -- posix system版本检查
_SC_PAGE_SIZE         -- 内存page大小获取
MAP_LOCKED            -- Linux里mmap里的swap特性

2.3 程序解析

让我们尝试分析memtester主函数入口main,main()函数最开始都是一些输入参数解析,其实主要就是为了获取三个重要变量:内存测试起始地址、内存测试总长度、压力测试循环次数,有了这三个变量值之后便开始逐一跑tests.c文件里各项测试算法小函数:

struct test {char *name;int (*fp)();
};struct test tests[] = {{ "Random Value", test_random_value },{ "Compare XOR", test_xor_comparison },{ "Compare SUB", test_sub_comparison },{ "Compare MUL", test_mul_comparison },{ "Compare DIV",test_div_comparison },{ "Compare OR", test_or_comparison },{ "Compare AND", test_and_comparison },{ "Sequential Increment", test_seqinc_comparison },{ "Solid Bits", test_solidbits_comparison },{ "Block Sequential", test_blockseq_comparison },{ "Checkerboard", test_checkerboard_comparison },{ "Bit Spread", test_bitspread_comparison },{ "Bit Flip", test_bitflip_comparison },{ "Walking Ones", test_walkbits1_comparison },{ "Walking Zeroes", test_walkbits0_comparison },
#ifdef TEST_NARROW_WRITES    { "8-bit Writes", test_8bit_wide_random },{ "16-bit Writes", test_16bit_wide_random },
#endif{ NULL, NULL }
};/* Function definitions */
void usage(char *me) {fprintf(stderr, "\n""Usage: %s [-p physaddrbase [-d device]] <mem>[B|K|M|G] [loops]\n",me);exit(EXIT_FAIL_NONSTARTER);
}int main(int argc, char **argv) {ul loops, loop, i;size_t bufsize, halflen, count;void volatile *buf, *aligned;ulv *bufa, *bufb;ul testmask = 0;// 省略若干变量定义代码printf("memtester version " __version__ " (%d-bit)\n", UL_LEN);printf("Copyright (C) 2001-2020 Charles Cazabon.\n");printf("Licensed under the GNU General Public License version 2 (only).\n");printf("\n");// 省略若干初始检查代码// 从输入参数里获取physaddrbase计算出内存测试起始地址aligned// 从输入参数里获取mem及B|K|M|G计算出内存测试总长度bufsizehalflen = bufsize / 2;count = halflen / sizeof(ul);bufa = (ulv *) aligned;bufb = (ulv *) ((size_t) aligned + halflen);// 压力测试的重要变量, loops即重复次数for(loop=1; ((!loops) || loop <= loops); loop++) {printf("Loop %lu", loop);if (loops) {printf("/%lu", loops);}printf(":\n");printf("  %-20s: ", "Stuck Address");fflush(stdout);// 第一个测试 stuck_addressif (!test_stuck_address(aligned, bufsize / sizeof(ul))) {printf("ok\n");} else {exit_code |= EXIT_FAIL_ADDRESSLINES;}// 遍历tests.c里的所有测试子程序for (i=0;;i++) {if (!tests[i].name) break;if (testmask && (!((1 << i) & testmask))) {continue;}printf("  %-20s: ", tests[i].name);// 可以看到将内存测试总空间一分为二,传给子程序做处理的if (!tests[i].fp(bufa, bufb, count)) {printf("ok\n");} else {exit_code |= EXIT_FAIL_OTHERTEST;}fflush(stdout);/* clear buffer */memset((void *) buf, 255, wantbytes);}printf("\n");fflush(stdout);}
}

tests.c文件里才是最核心的压力测试算法子程序,一共17个函数,涉及各种内存访问经验操作,具体可以看网上的一篇详细解析文章 https://www.jianshu.com/p/ef203c360c4f。

测试函数名 测试作用
test_stuck_address 先全部把地址值交替取反放入对应存储位置,然后再读出比较,重复n次
test_random_value 等效test_random_comparison(bufa, bufb, count):数据敏感型测试用例
test_xor_comparison 与test_random_value比多了个异或操作
test_sub_comparison 与test_random_value比多了个减法操作
test_mul_comparisone 与test_random_value比多了个乘法操作
test_div_comparison 与test_random_value比多了个除法操作
test_or_comparison 在test_random_comparison()里面合并了
test_and_comparison 在test_random_comparison()里面合并了
test_seqinc_comparison 是 test_blockseq_comparison的一个子集;模拟客户压力测试场景
test_solidbits_comparison 固定全1后写入两个buffer,然后读出比较,然后全0写入读出比较;这就是Zero-One算法
test_blockseq_comparison 一次写一个count大小的块,写的值是拿byte级的数填充32bit,然后取出对比,接着重复256次;也是压力用例,只是次数变多了;
test_checkerboard_comparison 把设定好的几组Data BackGround,依次写入,然后读出比较
test_bitspread_comparison 还是在32bit里面移动,只是这次移动的不是单单的一个0或者1,而是两个1,这两个1之间隔着两个空位/td>
test_bitflip_comparison 也是32bit里面的一个bit=1不断移动生成data pattern然后,每个pattern均执行
test_walkbits1_comparison 与test_walkbits0_comparison同理
test_walkbits0_comparison 就是bit=1的位置在32bit里面移动,每移动一次就全部填满buffer,先是从低位往高位移,再是从高位往低位移动
test_8bit_wide_random 以char指针存值,也就是每次存8bit,粒度更细;
test_16bit_wide_random 以unsigned short指针存值,也就是每次存16bit,不同粒度检测;

2.4 结果格式

在Unix-like系统下使用make && make install命令进行编译可得到一个可执行的memtester,可以随便执行memtester 10M 1,即申请10M的内存测试1次,结果如下:

[root@as150 ~] memtester 10M 1memtester version 4.5.0 (64-bit)
Copyright (C) 2001-2020 Charles Cazabon.
Licensed under the GNU General Public License version 2 (only).pagesize is 4096
pagesizemask is 0xfffffffffffff000
want 10MB (10485760 bytes)
got  10MB (10485760 bytes), trying mlock ...locked.
Loop 1/1:Stuck Address: okRandom Value: okCompare XOR: okCompare SUB: okCompare MUL: okCompare DIV: okCompare OR: okCompare AND: okSequential Increment: okSolid Bits: okBlock Sequential: okCheckerboard: okBit Spread: okBit Flip: okWalking Ones: okWalking Zeroes: ok8-bit Writes: ok16-bit Writes: okDone.

至此,内存读写正确性压力测试程序memtester痞子衡便介绍完毕了,掌声在哪里~~~


推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

嵌入式里如何给内存做压力测试?不妨试试memtester相关推荐

  1. 痞子衡嵌入式:在i.MXRT1060-EVK上利用memtester程序给SDRAM做压力测试

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是在i.MXRT1060-EVK上利用memtester程序给SDRAM做压力测试. 我们知道恩智浦i.MXRT1xxx系列是高性能MCU ...

  2. Linux学习13-CentOS安装ab做压力测试

    前言 网站性能压力测试是服务器网站性能调优过程中必不可缺少的一,测试环境准备好了后,如何对网站做压力测试? 压力测试的工具很多,如:ab.http_load.webbench.siege.jmeter ...

  3. 不会压测?没关系,手把手教你用jmeter做压力测试及结果分析

    1.准备 测试之前需要先准备相关的工具,JMeter是运行在jdk下的一款压测工具,所以,要运行JMeter首选要安装jdk并配置环境变量,具体请自行百度jdk环境变量安装: 2.JMeter 是什么 ...

  4. 什么是压力测试,在哪里做压力测试,软件压力测试存在哪些问题?

    软件压力测试是一种基本的质量保证行为,它是每个重要软件测试工作的一部分.软件压力测试的基本思路很简单: 不是在常规条件下运行手动或自动测试,而是在计算机数量较少或系统资源匮乏的条件下运行测试. 通常要 ...

  5. 如何用Jmeter做压力测试

    Jmeter是一个性能测试工具,同loadrunner类似,他功能较多,我们常用的功能是用jmeter模拟多浏览器对网站做压力测试. 我们一般的网站,在进入业务功能前先需登录,然后才能访问业务功能.下 ...

  6. 性能测试入门(六)windows及Linux下做压力测试的注册表设置

    windows及Linux下做压力测试的注册表设置 from: http://www.cnblogs.com/tianzhiliang/articles/2400176.html TcpTimedWa ...

  7. 接口压力测试:Postman【Postman通常用于做接口测试,同时也可以用于作为压力测试】、Jmeter【专门做压力测试】、Loadrunner、Apache AB、Webbench

    做开发的同学一定会遇到接口对接,今天介绍两个对接测试两个我个人认为比较好的测试工具 postman和jmeter 1.postman通常用于做接口测试,同时也可以用于作为压力测试 2.jmeter做压 ...

  8. 性能测试,如何做压力测试?压力测试实施,避免背锅提升效率(二)

    目录:导读 前言 一.目标制定以及业务规则梳理 1.目标制定 2.业务规则的调研 二.部署架构调研 三.对测试数据进行调研 1.数据库基础数据量分析 2.压测增量数据分析 3.冷热数据的分析 四.测试 ...

  9. html开发的移动端怎么做压力测试,移动端压力测试

    移动端压力测试 移动端压力测试 一.monkey APP性能测试 (adb shell monkey 1000 adb logcat | gerp START获取包名和activity名 adb sh ...

最新文章

  1. java原始模型模式_java设计模式--原始模型模式
  2. A*算法解决八数码问题 Java语言实现
  3. ntu ERIC 课程笔记
  4. 2016级算法第六次上机-A.Bamboo之寻找小金刚
  5. [Mac入门] 如果更快的打开程序或文件
  6. 余承东回应“卸任”传闻:服务还未拼尽全力,岂敢先溜
  7. 关于Clipboard剪切板获取值为NULL问题解决方法
  8. 以太坊 solidity 函数的完整声明格式
  9. Python爬取QQ音乐并下载
  10. 机器人仿真软件 V-REP学习记录(序言)
  11. 高音质无线蓝牙耳机推荐,2020游戏低延迟蓝牙耳机分享
  12. 网络正常但Chrome不能上网的解决方法
  13. oracle计算本年第几周,详细讲解“Oracle”数据库的“周数计算”
  14. bcm43142 linux 驱动下载,CentosRedhat下bcm43142博通无线网卡linux驱动之二
  15. iOS Core Animation 简明系列教程
  16. 牛客暑假多校第二场 K carpet
  17. 计算机常见故障及排除方法,科学网—计算机常见故障和解决办法 - 李卓哲的博文...
  18. Data Abort产生的原因
  19. STM32F767多通道ADC采集+DMA传输
  20. RSA加密解密C++实现

热门文章

  1. 分布式资本沈波:未来区块链杀手级应用将出现在“+区块链”
  2. mapreduce shuffle过程问答
  3. 订单编号,递增且不连续(php版)
  4. 39--打印从1到最大的n位数
  5. python与android交互,Android客户端与Python服务器端的简单通信
  6. linux系统页面缓存,Linux缓存机制之页缓存
  7. Linux环境下Mysql的安装教程及安装过程常见问题的解决方法
  8. 新手使用GitHub客户端提交项目的步骤
  9. java 四舍五入_Java常用类
  10. JPG PNG GIF BMP图片格式的区别