ESP 芯片 TF 卡速率测试

测试条件:

  • ESP32-S3
  • ESP-IDF 版本:v5.1.5
  • 闪迪 32G U1 CLASS 10 TF 卡
  • FAT32 文件系统,簇大小 4K

测试方法:

每次读取 4K 大小,循环读取,总共读取 16777KB 大小文件,计算平均速率

测试结果:

测试项目fread1fread(setvbuf NULL)fread(setvbuf 4K 内部内存)readread(buffer 未 4 字节对齐或为 PSRAM 内存)2
SDIO 4 线模式(40MHz)1594KB/S35KB/S7636KB/S7657KB/S1808KB/S
SDIO 1 线模式(40MHz)1286KB/S35KB/S3470KB/S3528KB/S1421KB/S
SPI 模式(20MHz)869KB/S34KB/S1579KB/S1592KB/S936KB/S
  1. fread 性能较差的原因在于,fread 的封装实现增加了一个缓冲区,每次通过 fread 读取数据,实际是从缓冲区拷贝数据;如果缓冲区没有所需数据,则先通过 read 接口读取数据到缓存区。而默认缓冲区大小为 128 字节,所以测试结果相对于 read 接口差距较大(见 提高 I/O 性能↩︎
  2. 当传给 read 的 buffer 为内部内存且 4 字节对齐时,能将读取操作一次性传递到 sdmmc/sdspi 层进行传输;否则传递给 sdmmc/sdspi 层之前会先申请 512 字节大小的内部内存,并将整个读取操作按照最大 512 字节拆分为多次给 sdmmc/sdspi 层操作,造成读取性能下降 ↩︎
SDIO 4 线测试 log

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0xa (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3818,len:0x14e0
load:0x403c9700,len:0x4
load:0x403c9704,len:0x1238
load:0x403cc700,len:0x2edc
entry 0x403c9900
I (00:00:00.012) sd_init: using pdrv=0
I (00:00:00.014) gpio: GPIO[14]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (00:00:00.016) gpio: GPIO[13]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (00:00:00.026) gpio: GPIO[21]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (00:00:00.036) gpio: GPIO[47]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (00:00:00.046) gpio: GPIO[11]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (00:00:00.056) gpio: GPIO[12]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 
I (00:00:00.137) sd_init: SD_INSERT
W (00:00:00.137) sd_init: Initializing SD card
I (00:00:00.190) gpio: GPIO[12]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (00:00:00.195) sd_init: SD_MOUNTED
Name: SC32G
Type: SDHC/SDXC
Speed: 40.00 MHz (limit: 40.00 MHz)
Size: 30436MB
CSD: ver=2, sector_size=512, capacity=62333952 read_bl_len=9
SSR: bus_width=4
I (00:00:01.057) eds main: file read test(size 16777KB)
W (00:00:01.060) eds main: test fread
I (00:00:01.060) eds main: fread start
I (00:00:11.585) eds main: fread end
W (00:00:11.585) eds main: fread speed:1594KB/S

W (00:00:11.586) eds main: test fread
W (00:00:11.588) eds main: setvbuf NULL
I (00:00:11.593) eds main: fread start
I (00:08:05.383) eds main: fread end
W (00:08:05.384) eds main: fread speed:35KB/S

W (00:08:05.386) eds main: test fread
W (00:08:05.387) eds main: setvbuf 4096
I (00:08:05.391) eds main: fread start
I (00:08:07.592) eds main: fread end
W (00:08:07.592) eds main: fread speed:7636KB/S

W (00:08:07.593) eds main: test read align(0x3fc981e0)
I (00:08:07.597) eds main: read start
I (00:08:09.792) eds main: read end
W (00:08:09.792) eds main: read speed:7657KB/S

W (00:08:09.793) eds main: test read unalign(0x3fc981e1)
I (00:08:09.797) eds main: read start
I (00:08:19.079) eds main: read end
W (00:08:19.080) eds main: read speed:1808KB/S

I (00:08:19.080) main_task: Returned from app_main()

SDIO 1 线测试 log

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0xa (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3818,len:0x14e0
load:0x403c9700,len:0x4
load:0x403c9704,len:0x1238
load:0x403cc700,len:0x2edc
entry 0x403c9900
I (00:00:00.012) sd_init: using pdrv=0
I (00:00:00.014) gpio: GPIO[14]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (00:00:00.016) gpio: GPIO[13]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (00:00:00.026) gpio: GPIO[21]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (00:00:00.036) gpio: GPIO[47]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (00:00:00.046) gpio: GPIO[11]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0 
I (00:00:00.056) gpio: GPIO[12]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 
I (00:00:00.137) sd_init: SD_INSERT
W (00:00:00.137) sd_init: Initializing SD card
I (00:00:00.195) sd_init: SD_MOUNTED
Name: SC32G
Type: SDHC/SDXC
Speed: 40.00 MHz (limit: 40.00 MHz)
Size: 30436MB
CSD: ver=2, sector_size=512, capacity=62333952 read_bl_len=9
SSR: bus_width=1
I (00:00:01.057) eds main: file read test(size 16777KB)
W (00:00:01.060) eds main: test fread
I (00:00:01.060) eds main: fread start
I (00:00:14.107) eds main: fread end
W (00:00:14.107) eds main: fread speed:1286KB/S

W (00:00:14.108) eds main: test fread
W (00:00:14.110) eds main: setvbuf NULL
I (00:00:14.114) eds main: fread start
I (00:08:10.427) eds main: fread end
W (00:08:10.428) eds main: fread speed:35KB/S

W (00:08:10.431) eds main: test fread
W (00:08:10.431) eds main: setvbuf 4096
I (00:08:10.435) eds main: fread start
I (00:08:15.273) eds main: fread end
W (00:08:15.273) eds main: fread speed:3470KB/S

W (00:08:15.274) eds main: test read align(0x3fc981e0)
I (00:08:15.278) eds main: read start
I (00:08:20.037) eds main: read end
W (00:08:20.037) eds main: read speed:3528KB/S

W (00:08:20.038) eds main: test read unalign(0x3fc981e1)
I (00:08:20.041) eds main: read start
I (00:08:31.846) eds main: read end
W (00:08:31.847) eds main: read speed:1421KB/S

I (00:08:31.847) main_task: Returned from app_main()

SPI 测试 log

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0xb (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3818,len:0x14e0
load:0x403c9700,len:0x4
load:0x403c9704,len:0x1238
load:0x403cc700,len:0x2edc
entry 0x403c9900
I (00:00:00.012) eds main: Initializing SD card
I (00:00:00.013) eds main: Using SPI peripheral
I (00:00:00.013) eds main: Mounting filesystem
I (00:00:00.017) gpio: GPIO[12]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (00:00:00.028) sdspi_transaction: cmd=52, R1 response: command not supported
I (00:00:00.068) sdspi_transaction: cmd=5, R1 response: command not supported
I (00:00:00.113) eds main: Filesystem mounted
Name: SC32G
Type: SDHC/SDXC
Speed: 20.00 MHz (limit: 20.00 MHz)
Size: 30436MB
CSD: ver=2, sector_size=512, capacity=62333952 read_bl_len=9
SSR: bus_width=1
I (00:00:00.122) eds main: file read test(size 16777KB)
W (00:00:00.131) eds main: test fread
I (00:00:00.132) eds main: fread start
I (00:00:19.426) eds main: fread end
W (00:00:19.426) eds main: fread speed:869KB/S

W (00:00:19.427) eds main: test fread
W (00:00:19.429) eds main: setvbuf NULL
I (00:00:19.433) eds main: fread start
I (00:08:21.862) eds main: fread end
W (00:08:21.862) eds main: fread speed:34KB/S

W (00:08:21.866) eds main: test fread
W (00:08:21.866) eds main: setvbuf 4096
I (00:08:21.869) eds main: fread start
I (00:08:32.497) eds main: fread end
W (00:08:32.497) eds main: fread speed:1579KB/S

W (00:08:32.498) eds main: test read align(0x3fc99cd0)
I (00:08:32.501) eds main: read start
I (00:08:43.038) eds main: read end
W (00:08:43.039) eds main: read speed:1592KB/S

W (00:08:43.040) eds main: test read unalign(0x3fc99cd1)
I (00:08:43.043) eds main: read start
I (00:09:00.955) eds main: read end
W (00:09:00.956) eds main: read speed:936KB/S

I (00:09:00.956) main_task: Returned from app_main()

非对齐读取测试:

打开文件后先读取一小块数据,使后续每次读取起始位置均未对齐文件系统的簇大小 4K。此处仅测试前面读取性能最佳的两种情况下的性能差异,SDIO 4线模式 40MHz

测试结果:

测试项目0123512 (TF 卡 block 大小对齐)1025
fread(setvbuf 4K 内部内存)7643KB/S7615KB/S7639KB/S7612KB/S
read7653KB/S1789KB/S5125KB/S1784KB/S
测试 log

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x1 (POWERON),boot:0xa (SPI_FAST_FLASH_BOOT)
SPIWP:0xee
mode:DIO, clock div:1
load:0x3fce3818,len:0x14e0
load:0x403c9700,len:0x4
load:0x403c9704,len:0x1238
load:0x403cc700,len:0x2edc
entry 0x403c9900
I (00:00:00.012) sd_init: using pdrv=0
I (00:00:00.014) gpio: GPIO[14]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (00:00:00.016) gpio: GPIO[13]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (00:00:00.026) gpio: GPIO[21]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (00:00:00.036) gpio: GPIO[47]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (00:00:00.046) gpio: GPIO[11]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (00:00:00.056) gpio: GPIO[12]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0
I (00:00:00.137) sd_init: SD_INSERT
W (00:00:00.137) sd_init: Initializing SD card
I (00:00:00.190) gpio: GPIO[12]| InputEn: 0| OutputEn: 0| OpenDrain: 0| Pullup: 1| Pulldown: 0| Intr:0
I (00:00:00.195) sd_init: SD_MOUNTED
I (00:00:01.057) eds main: file read test(size 16777KB)
W (00:00:01.060) eds main: test fread
W (00:00:01.060) eds main: setvbuf 4096
I (00:00:01.061) eds main: fread start
I (00:00:03.260) eds main: fread end
W (00:00:03.260) eds main: fread speed:7643KB/S

W (00:00:03.261) eds main: test fread
W (00:00:03.263) eds main: setvbuf 4096
W (00:00:03.268) eds main: offset 123
I (00:00:03.275) eds main: fread start
I (00:00:05.480) eds main: fread end
W (00:00:05.480) eds main: fread speed:7615KB/S

W (00:00:05.481) eds main: test fread
W (00:00:05.483) eds main: setvbuf 4096
W (00:00:05.487) eds main: offset 512
I (00:00:05.494) eds main: fread start
I (00:00:07.692) eds main: fread end
W (00:00:07.692) eds main: fread speed:7639KB/S

W (00:00:07.693) eds main: test fread
W (00:00:07.695) eds main: setvbuf 4096
W (00:00:07.700) eds main: offset 1025
I (00:00:07.707) eds main: fread start
I (00:00:09.912) eds main: fread end
W (00:00:09.913) eds main: fread speed:7612KB/S

W (00:00:09.914) eds main: test read align(0x3fc981e0)
I (00:00:09.917) eds main: read start
I (00:00:12.113) eds main: read end
W (00:00:12.113) eds main: read speed:7653KB/S

W (00:00:12.114) eds main: test read align(0x3fc981e0)
W (00:00:12.117) eds main: offset 123
I (00:00:12.122) eds main: read start
I (00:00:21.499) eds main: read end
W (00:00:21.500) eds main: read speed:1789KB/S

W (00:00:21.500) eds main: test read align(0x3fc981e0)
W (00:00:21.504) eds main: offset 512
I (00:00:21.511) eds main: read start
I (00:00:24.785) eds main: read end
W (00:00:24.785) eds main: read speed:5125KB/S

W (00:00:24.786) eds main: test read align(0x3fc981e0)
W (00:00:24.789) eds main: offset 1025
I (00:00:24.795) eds main: read start
I (00:00:34.199) eds main: read end
W (00:00:34.199) eds main: read speed:1784KB/S

I (00:00:34.199) main_task: Returned from app_main()

补充:上述非对齐测试,是通过 fread/read 读取一小节数据来调整测试起始读取位置非对齐;如果 fread 测试,改用 fseek 直接调整读取起始位置到非对齐位置,则读取性能也会下降(offset 为 123、512、1025 的测试情况分别为 1772KB/S、4999KB/S、1766KB/S,与 read 情况接近)。因此建议需要修改读取位置的时候,先使用 fseek 调整到 fread 缓冲区大小对齐位置,再使用 fread 补齐剩余非对齐部分偏移。

总结:

在内存充足或有 PSRAM 的情况下,如果应用层读取无法保证簇对齐、buffer 空间为内部内存、buffer 地址 4 字节对齐等这几种情况,建议使用 fread 接口,并设置 4K 或者簇大小的内部内存缓冲 buffer;其他情况则使用 read 接口

测试代码

#define TEST_LEN    4*1024
#define TEST_COUNT 4*1024

uint8_t read_buff[TEST_LEN + 1];

uint8_t f_buff[0x1000];

void test_fread(bool set_buff, size_t buff_len, uint32_t offset)
{
    uint32_t time_start, time_end;
    int speed;
    FILE *f;
    f = fopen("/sdcard/test.bin", "r");
    if (f != NULL) {
        ESP_LOGW(TAG, "test fread");
        if (set_buff) {
            if (buff_len) {
                ESP_LOGW(TAG, "setvbuf %d", buff_len);
                setvbuf(f, (char *)f_buff, _IOFBF, buff_len);
            } else {
                ESP_LOGW(TAG, "setvbuf NULL");
                setvbuf(f, NULL, _IONBF, 0);
            }
        }
        if(offset){
            if(offset > TEST_LEN){
                offset = TEST_LEN;
            }
            ESP_LOGW(TAG, "offset %"PRIu32, offset);
            fread(read_buff, offset, 1, f);
        }
        ESP_LOGI(TAG, "fread start");
        time_start = esp_timer_get_time() / 1000;
        for (int i = 0;i < TEST_COUNT;i++) {
            fread(read_buff, TEST_LEN, 1, f);
        }
        time_end = esp_timer_get_time() / 1000;
        ESP_LOGI(TAG, "fread end");
        fclose(f);
        speed = TEST_LEN * TEST_COUNT / (time_end - time_start);
        ESP_LOGW(TAG, "fread speed:%dKB/S\n", speed);
    }
}

void test_read(bool align, uint32_t offset)
{
    uint32_t time_start, time_end;
    int speed;
    int fd;
    fd = open("/sdcard/test.bin", O_RDONLY);
    uint8_t *buff = read_buff;

    if (fd >= 0) {
        if (align) {
            ESP_LOGW(TAG, "test read align(%p)", buff);
        } else {
            buff += 1;
            ESP_LOGW(TAG, "test read unalign(%p)", buff);
        }
        if(offset){
            if(offset > TEST_LEN){
                offset = TEST_LEN;
            }
            ESP_LOGW(TAG, "offset %"PRIu32, offset);
            read(fd, buff, offset);
        }
        
        ESP_LOGI(TAG, "read start");
        time_start = esp_timer_get_time() / 1000;
        for (int i = 0;i < TEST_COUNT;i++) {
            read(fd, buff, TEST_LEN);
        }
        time_end = esp_timer_get_time() / 1000;
        ESP_LOGI(TAG, "read end");
        close(fd);
        speed = TEST_LEN * TEST_COUNT / (time_end - time_start);
        ESP_LOGW(TAG, "read speed:%dKB/S\n", speed);
    }
}

void file_test()
{
    ESP_LOGI(TAG, "file read test(size %dKB)", TEST_LEN * TEST_COUNT / 1000);
#if 1
    test_fread(false, 0, 0);
    test_fread(true, 0, 0);
    test_fread(true, 4096, 0);

    test_read(true, 0);
    test_read(false, 0);
#else
    test_fread(true, 4096, 0);
    test_fread(true, 4096, 123);
    test_fread(true, 4096, 512);
    test_fread(true, 4096, 1025);

    test_read(true, 0);
    test_read(true, 123);
    test_read(true, 512);
    test_read(true, 1025);
#endif
}

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇