手机的硬件配置越来越强悍。存储容量需求越大,机身存储容量都达到128G了,那么对读、写性能的要求也会越高啦!
哈哈,总不能让豪华跑车用脱拉机的轮胎吧!,也许比喻不是很准。 总之, 个人认为存储性能是整个系统的性能重要一环。
注:
1、本文所示的所有测试对比数据都源自相同的硬件配置:
cpu : MT6582 + memory: KMK8X000VM_B412(1G+16G)
2、测试工具:iozone , ./iozone -a -n 1G -g 2G -i 0 -i 1 -f /mnt/shell/emulated/0/iozone.tmp -Rb /mnt/shell/emulated/0/iozone.xls
3、仅连续读写测试。随机读写数据没有展现出来。
参考本人的另一个blog文章《基于fuse文件系统的android fuse sdcard设计访案》
android默认在emmc上使用的如下三种文件系统:
1、ext4
2、vfat
3、fuse
另外,添加两个新型文件系统:
4、wrapfs
5、f2fs
android用户数据data分区默认使用ext4文件系统,下面是ext4的测试数据:
Writer Report | ||||||||||||||
4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | ||
1048576 | 0 | 0 | 0 | 0 | 41545 | 42121 | 42476 | 42773 | 42856 | 43246 | 42631 | 42857 | 42647 | |
2097152 | 0 | 0 | 0 | 0 | 42150 | 41562 | 42512 | 43086 | 42386 | 43314 | 42830 | 42767 | 43122 | |
Reader Report | ||||||||||||||
4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | ||
1048576 | 0 | 0 | 0 | 0 | 87540 | 88999 | 89005 | 88668 | 87543 | 89140 | 88588 | 88584 | 88976 | |
2097152 | 0 | 0 | 0 | 0 | 89477 | 86422 | 89588 | 89715 | 89664 | 89349 | 88440 | 88993 | 88873 |
android GB版本内置sdcard和用户数据区data使用独立的分区,默认内置sdcard使用vfat文件系统。
下面是vfat的测试数据:
Writer Report | |||||||||||||
4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | |
1048576 | 0 | 0 | 0 | 0 | 10915 | 11080 | 10901 | 11129 | 11092 | 11043 | 10780 | 10883 | 10998 |
2097152 | 0 | 0 | 0 | 0 | 11008 | 10962 | 10766 | 11229 | 10933 | 10783 | 10972 | 10869 | 10919 |
Reader Report | |||||||||||||
4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | |
1048576 | 0 | 0 | 0 | 0 | 86012 | 85904 | 85306 | 84664 | 84975 | 84843 | 82775 | 83946 | 83816 |
2097152 | 0 | 0 | 0 | 0 | 83136 | 83501 | 84052 | 83296 | 83559 | 83162 | 83184 | 83213 | 82932 |
android JB、KK版本内置sdcard使用fuse文件系统,取代了传统的vfat。
下面是fuse的测试数据:
Writer Report | |||||||||||||
4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | |
1048576 | 0 | 0 | 0 | 0 | 23911 | 23533 | 23673 | 23799 | 23750 | 23496 | 23797 | 23703 | 23827 |
2097152 | 0 | 0 | 0 | 0 | 21698 | 23686 | 23526 | 23529 | 23555 | 23532 | 23548 | 23693 | 23755 |
Reader Report | |||||||||||||
4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | |
1048576 | 0 | 0 | 0 | 0 | 45536 | 45496 | 45094 | 45454 | 45415 | 45438 | 45309 | 45806 | 45961 |
2097152 | 0 | 0 | 0 | 0 | 47964 | 48054 | 48215 | 48159 | 48310 | 48350 | 48370 | 48335 | 48356 |
1048576 | 0 | 0 | 0 | 0 | 42087 | 42073 | 42733 | 42875 | 42801 | 43023 | 43465 | 42733 | 43419 |
2097152 | 0 | 0 | 0 | 0 | 41696 | 42271 | 42732 | 42446 | 42917 | 43432 | 42769 | 43180 | 43097 |
Reader Report | |||||||||||||
4 | 8 | 16 | 32 | 64 | 128 | 256 | 512 | 1024 | 2048 | 4096 | 8192 | 16384 | |
1048576 | 0 | 0 | 0 | 0 | 93034 | 92754 | 93030 | 91321 | 92298 | 92093 | 92011 | 92517 | 93373 |
2097152 | 0 | 0 | 0 | 0 | 92531 | 92389 | 92514 | 91889 | 92107 | 91777 | 92493 | 92524 | 92012 |
上面测试数据对比结果如下图:
mtk平台可以通过mmc block层和mmc driver层的log进一步性能问题分析:
1、 mmc block层log:
/kernel/drivers/mmc/card/block.c
static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *rqc)
{
if(t_period >= (unsigned long long )PRT_TIME_PERIOD)
{
mmcqd_read_clear[idx] = 2;
mmcqd_work_percent[idx] = 1;
mmcqd_r_throughput[idx] = 0;
mmcqd_w_throughput[idx] = 0;
t_usage = mmcqd_t_usage_wr [idx] + mmcqd_t_usage_rd[idx];
if(t_period > t_usage*100)
xlog_printk(ANDROID_LOG_DEBUG, "BLOCK_TAG", "mmcqd:%d Workload < 1%%, duty %lld, period %lld, req_cnt=%d \n", mmcqd[idx], t_usage, t_period, mmcqd_rq_count[idx]);
else
{
do_div(t_period, 100);//boundary issue
t_percent =((unsigned int)t_usage)/((unsigned int)t_period);
mmcqd_work_percent[idx] = t_percent;
xlog_printk(ANDROID_LOG_DEBUG, "BLOCK_TAG", "mmcqd:%d Workload=%d%%, duty %lld, period %lld00, req_cnt=%d \n", mmcqd[idx], t_percent, t_usage, t_period, mmcqd_rq_count[idx]);//period %lld00 == period %lld x100
}
if(mmcqd_wr_rq_count[idx] >= 2)
{
diversity = mmcqd_wr_offset[idx]/(mmcqd_wr_rq_count[idx]-1);
xlog_printk(ANDROID_LOG_DEBUG, "BLOCK_TAG", "mmcqd:%d Write Diversity=%d sectors offset, req_cnt=%d, break_cnt=%d, tract_cnt=%d, bit_cnt=%d\n", mmcqd[idx], diversity, mmcqd_wr_rq_count[idx], mmcqd_wr_break[idx], mmcqd_wr_tract[idx], mmcqd_wr_bit[idx]);
}
if(mmcqd_rd_rq_count[idx] >= 2)
{
diversity = mmcqd_rd_offset[idx]/(mmcqd_rd_rq_count[idx]-1);
xlog_printk(ANDROID_LOG_DEBUG, "BLOCK_TAG", "mmcqd:%d Read Diversity=%d sectors offset, req_cnt=%d, break_cnt=%d, tract_cnt=%d, bit_cnt=%d\n", mmcqd[idx], diversity, mmcqd_rd_rq_count[idx], mmcqd_rd_break[idx], mmcqd_rd_tract[idx], mmcqd_rd_bit[idx]);
}
if(mmcqd_t_usage_wr[idx])
{
do_div(mmcqd_t_usage_wr[idx], 1000000);//boundary issue
if(mmcqd_t_usage_wr[idx])// discard print if duration will <1ms
{
perf_meter = (mmcqd_rq_size_wr[idx])/((unsigned int)mmcqd_t_usage_wr[idx]); //kb/s
mmcqd_w_throughput[idx] = perf_meter;
xlog_printk(ANDROID_LOG_DEBUG, "BLOCK_TAG", "mmcqd:%d Write Throughput=%d kB/s, size: %d bytes, time:%lld ms\n", mmcqd[idx], perf_meter, mmcqd_rq_size_wr[idx], mmcqd_t_usage_wr[idx]);
}
}
if(mmcqd_t_usage_rd[idx])
{
do_div(mmcqd_t_usage_rd[idx], 1000000);//boundary issue
if(mmcqd_t_usage_rd[idx])// discard print if duration will <1ms
{
perf_meter = (mmcqd_rq_size_rd[idx])/((unsigned int)mmcqd_t_usage_rd[idx]); //kb/s
mmcqd_r_throughput[idx] = perf_meter;
xlog_printk(ANDROID_LOG_DEBUG, "BLOCK_TAG", "mmcqd:%d Read Throughput=%d kB/s, size: %d bytes, time:%lld ms\n", mmcqd[idx], perf_meter, mmcqd_rq_size_rd[idx], mmcqd_t_usage_rd[idx]);
}
}
}
打印log如下:
<6>[ 4300.322225] (1)[70:mmcqd/0][BLOCK_TAG] mmcqd:70 Workload=48%, duty 252014307, period 516096500, req_cnt=23
<6>[ 4300.322254] (1)[70:mmcqd/0][BLOCK_TAG] mmcqd:70 Write Diversity=0 sectors offset, req_cnt=24, break_cnt=0, tract_cnt=22, bit_cnt=0
<6>[ 4300.322282] (1)[70:mmcqd/0][BLOCK_TAG] mmcqd:70 Write Throughput=45771 kB/s, size: 11534336 bytes, time:252 ms
2、mmc driver层的log:
/platform/mt6582/kernel/drivers/mmc-host/sd.c
static void msdc_pre_req(struct mmc_host *mmc, struct mmc_request *mrq, bool is_first_req)
{
N_MSG(OPS, "CMD<%d> ARG<0x%x>data<%s %s> blksz<%d> block<%d> error<%d>",mrq->cmd->opcode,mrq->cmd->arg, (data->host_cookie ? "dma":"pio"),
(read ? "read ":"write") ,data->blksz, data->blocks, data->error);
}
static void msdc_post_req(struct mmc_host *mmc, struct mmc_request *mrq, int err)
{
N_MSG(OPS, "CMD<%d> ARG<0x%x> blksz<%d> block<%d> error<%d>",mrq->cmd->opcode,mrq->cmd->arg,
data->blksz, data->blocks, data->error);
}
打印log如下:
<3>[ 4262.661904] (0)[70:mmcqd/0]msdc0 -> CMD<25> ARG<0x4a4800>data
<3>[ 4262.662826] (0)[70:mmcqd/0]msdc0 -> CMD<25> ARG<0x4a4c00>data
<3>[ 4262.670118] (0)[70:mmcqd/0]msdc0 -> CMD<25> ARG<0x4a4800> blksz<512> block<1024> error<0> <- msdc_post_req() : L<6113> PID
<3>[ 4262.672084] (0)[70:mmcqd/0]msdc0 -> CMD<25> ARG<0x4a5000>data
<3>[ 4262.677840] (0)[70:mmcqd/0]msdc0 -> CMD<25> ARG<0x4a4c00> blksz<512> block<1024> error<0> <- msdc_post_req() : L<6113> PID
<3>[ 4262.679806] (0)[70:mmcqd/0]msdc0 -> CMD<25> ARG<0x4a5400>data
<3>[ 4262.708886] (0)[70:mmcqd/0]msdc0 -> CMD<25> ARG<0x4a5000> blksz<512> block<1024> error<0> <- msdc_post_req() : L<6113>