Skip to content

Commit b1ad3bb

Browse files
committed
add a post on speed test
1 parent e69e537 commit b1ad3bb

File tree

2 files changed

+294
-0
lines changed

2 files changed

+294
-0
lines changed
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
#+OPTIONS: ^:nil
2+
#+BEGIN_EXPORT html
3+
---
4+
layout: default
5+
title: 一种基于ESP32丰富连接能力的移动存储设备 -- 测试TF读写速度
6+
tags: [Rust on ESP, ESP32, SPI, SDMMC, TFCARD]
7+
nav_order: {{ page.date }}
8+
sync_wexin: 1
9+
---
10+
#+END_EXPORT
11+
12+
* 一种基于ESP32丰富连接能力的移动存储设备 -- 测试TF读写速度
13+
14+
** 前言
15+
16+
在前面的文章中我已经验证了TF卡读写功能,证实了我们可以通过ESP-IDF的接口访问FAT格式的TF卡。为了验证通过WebDAV协议访问TF卡的体验,我将WebDAV前端和TF卡访问功能集成到了一起,使得WebDAV模块可以从TF卡挂载的位置读取文件。本文是我的测试过程。
17+
18+
本系列其他文章
19+
1. [[https://paul356.github.io/2024/10/31/mobile-storage.html][基于ESP32的移动存储设备]]
20+
2. [[https://paul356.github.io/2024/12/12/mobile-storage-pcb.html][一种基于ESP32丰富连接能力的移动存储设备 -- 电路设计]]
21+
3. [[https://paul356.github.io/2024/12/27/mobile-storage-sd-card-test.html][一种基于ESP32丰富连接能力的移动存储设备 -- 测试SD卡读写]]
22+
4. [[https://paul356.github.io/2025/01/06/mobile-storage-display.html][一种基于ESP32丰富连接能力的移动存储设备 -- 验证屏幕显示]]
23+
24+
** 测试micro-storage
25+
26+
本文使用的代码都可以在代码仓库[[https://github.com/paul356/esp-webdav][esp-webdav]]中找到。
27+
28+
*** 测试顺序读取速度
29+
30+
我们希望测得TF卡的顺序读取速度,因为通过WebDAV协议访问基本上不会有随机读取的场景,我就没有测试随机读写场景。为了测试无干扰下的TF卡顺序读取速度,我写了一个顺序读取一个大文件的函数。
31+
32+
#+begin_src Rust
33+
async fn test_file_perf(mount_point: &str) -> anyhow::Result<()> {
34+
let file_path = format!("{}/habanera.mp4", mount_point);
35+
36+
tokio::task::spawn(async move {
37+
let mut file = tokio::fs::File::open(file_path).await?;
38+
let mut read_buf = std::vec![0;32*1024];
39+
let mut read_size: usize = 0;
40+
41+
let beg = tokio::time::Instant::now();
42+
43+
for _i in 0..400 {
44+
let size = file.read(&mut read_buf).await?;
45+
read_size += size;
46+
}
47+
48+
info!("[Async] Read {} bytes in {:?}", read_size, beg.elapsed());
49+
50+
Ok::<_, anyhow::Error>(())
51+
}).await?
52+
}
53+
54+
fn test_file_sync(mount_point: &str) -> anyhow::Result<()> {
55+
let file_path = format!("{}/habanera.mp4", mount_point);
56+
let mut file = std::fs::File::open(file_path)?;
57+
let mut read_buf = std::vec![0;32*1024];
58+
let mut read_size: usize = 0;
59+
60+
let beg = tokio::time::Instant::now();
61+
62+
use std::io::Read;
63+
for _i in 0..400 {
64+
let size = file.read(&mut read_buf).unwrap();
65+
read_size += size;
66+
}
67+
68+
info!("[Sync] Read {} bytes in {:?}", read_size, beg.elapsed());
69+
70+
Ok::<_, anyhow::Error>(())
71+
}
72+
73+
#+end_src
74+
75+
用于测试的文件位于TF根目录下,大约有100MB。测试方法很简单,每次读取32KB的文件内容,连续请求200次,最后获取消耗的时间。
76+
77+
#+begin_src text
78+
I (1709) micro_storage: [Sync] Read 13107200 bytes in 1.593215s
79+
...
80+
I (21727) micro_storage: [Async] Read 13107200 bytes in 4.229245s
81+
#+end_src
82+
83+
我共测试了两次,第一次使用同步接口,第二次使用了tokio库的异步接口。使用异步接口后同样的任务时间却增加了2.6秒,大概由于只有一个并发请求,增加了开销但没有带来收益。但增加的时延具体耗费在哪些事情上了,还需要进一步分析。对于ESP32这样的资源受限的平台,使用异步编程接口可能是”杀鸡用了牛刀“。同步读的速度约为7.9MB/秒,异步读的速度约为3.0MB/秒。
84+
85+
*** 测试顺序写速度
86+
87+
测试顺序写速度使用了和测试顺序读类似的方法。而且也测试了一次同步接口和一次异步接口。
88+
89+
#+begin_src Rust
90+
async fn test_wfile_perf(mount_point: &str) -> anyhow::Result<()> {
91+
let file_path = format!("{}/wfile_async.bin", mount_point);
92+
93+
tokio::task::spawn(async move {
94+
let mut file = tokio::fs::File::create(file_path).await?;
95+
let mut write_buf = std::vec![0xfu8;32*1024];
96+
let mut write_size: usize = 0;
97+
98+
let beg = tokio::time::Instant::now();
99+
100+
for _i in 0..400 {
101+
let size = file.write(&mut write_buf).await?;
102+
write_size += size;
103+
}
104+
105+
info!("[Async] Write {} bytes in {:?}", write_size, beg.elapsed());
106+
107+
Ok::<_, anyhow::Error>(())
108+
}).await?
109+
}
110+
111+
fn test_wfile_sync(mount_point: &str) -> anyhow::Result<()> {
112+
let file_path = format!("{}/wfile_sync.bin", mount_point);
113+
let mut file = std::fs::File::create(file_path)?;
114+
let mut write_buf = std::vec![3u8;32*1024];
115+
let mut write_size: usize = 0;
116+
117+
let beg = tokio::time::Instant::now();
118+
119+
use std::io::Write;
120+
for _i in 0..400 {
121+
let size = file.write(&mut write_buf).unwrap();
122+
write_size += size;
123+
}
124+
125+
info!("[Sync] Write {} bytes in {:?}", write_size, beg.elapsed());
126+
127+
Ok::<_, anyhow::Error>(())
128+
}
129+
#+end_src
130+
131+
测试结果如下。经过计算同步写的速度大约为3MB/秒,而异步写速度只有1.8MB/秒。
132+
133+
#+begin_src text
134+
I (6263) micro_storage: [Sync] Write 13107200 bytes in 4.11604s
135+
...
136+
I (29223) micro_storage: [Async] Write 13107200 bytes in 7.079895s
137+
#+end_src
138+
139+
** 总结
140+
141+
我们得到同步顺序读写的速度为7.9MB/秒和3MB/秒,异步接口的顺序读写性能要差一些,为3MB/秒和1.8MB/秒。前一对数字还差强人意,后一对数字就有点难看了。但是我们的WebDAV程序正是使用的异步接口,所以读写性能不会太好。本来想实际测试WebDAV程序的下载和上传性能,但是因为系统经常报告内存不够,导致系统OOM。虽然我的ESP32S3模块有8MB的SPIRAM,但是我发现启用了SPIRAM之后,会出现无法挂载TF卡的错误,我怀疑是硬件设计的问题,所以展示无法对性能进行端到端测试。
142+
143+
** 链接
144+
1. esp_webdav - https://github.com/paul356/esp-webdav
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
---
2+
layout: default
3+
title: 一种基于ESP32丰富连接能力的移动存储设备 -- 测试TF读写速度
4+
tags: [Rust on ESP, ESP32, SPI, SDMMC, TFCARD]
5+
nav_order: {{ page.date }}
6+
sync_wexin: 1
7+
---
8+
9+
10+
# 一种基于ESP32丰富连接能力的移动存储设备 &#x2013; 测试TF读写速度
11+
12+
13+
## 前言
14+
15+
在前面的文章中我已经验证了TF卡读写功能,证实了我们可以通过ESP-IDF的接口访问FAT格式的TF卡。为了验证通过WebDAV协议访问TF卡的体验,我将WebDAV前端和TF卡访问功能集成到了一起,使得WebDAV模块可以从TF卡挂载的位置读取文件。本文是我的测试过程。
16+
17+
本系列其他文章
18+
19+
1. [基于ESP32的移动存储设备](https://paul356.github.io/2024/10/31/mobile-storage.html)
20+
2. [一种基于ESP32丰富连接能力的移动存储设备 &#x2013; 电路设计](https://paul356.github.io/2024/12/12/mobile-storage-pcb.html)
21+
3. [一种基于ESP32丰富连接能力的移动存储设备 &#x2013; 测试SD卡读写](https://paul356.github.io/2024/12/27/mobile-storage-sd-card-test.html)
22+
4. [一种基于ESP32丰富连接能力的移动存储设备 &#x2013; 验证屏幕显示](https://paul356.github.io/2025/01/06/mobile-storage-display.html)
23+
24+
25+
## 测试micro-storage
26+
27+
本文使用的代码都可以在代码仓库[esp-webdav](https://github.com/paul356/esp-webdav)中找到。
28+
29+
30+
### 测试顺序读取速度
31+
32+
我们希望测得TF卡的顺序读取速度,因为通过WebDAV协议访问基本上不会有随机读取的场景,我就没有测试随机读写场景。为了测试无干扰下的TF卡顺序读取速度,我写了一个顺序读取一个大文件的函数。
33+
34+
```Rust
35+
async fn test_file_perf(mount_point: &str) -> anyhow::Result<()> {
36+
let file_path = format!("{}/habanera.mp4", mount_point);
37+
38+
tokio::task::spawn(async move {
39+
let mut file = tokio::fs::File::open(file_path).await?;
40+
let mut read_buf = std::vec![0;32*1024];
41+
let mut read_size: usize = 0;
42+
43+
let beg = tokio::time::Instant::now();
44+
45+
for _i in 0..400 {
46+
let size = file.read(&mut read_buf).await?;
47+
read_size += size;
48+
}
49+
50+
info!("[Async] Read {} bytes in {:?}", read_size, beg.elapsed());
51+
52+
Ok::<_, anyhow::Error>(())
53+
}).await?
54+
}
55+
56+
fn test_file_sync(mount_point: &str) -> anyhow::Result<()> {
57+
let file_path = format!("{}/habanera.mp4", mount_point);
58+
let mut file = std::fs::File::open(file_path)?;
59+
let mut read_buf = std::vec![0;32*1024];
60+
let mut read_size: usize = 0;
61+
62+
let beg = tokio::time::Instant::now();
63+
64+
use std::io::Read;
65+
for _i in 0..400 {
66+
let size = file.read(&mut read_buf).unwrap();
67+
read_size += size;
68+
}
69+
70+
info!("[Sync] Read {} bytes in {:?}", read_size, beg.elapsed());
71+
72+
Ok::<_, anyhow::Error>(())
73+
}
74+
75+
```
76+
77+
用于测试的文件位于TF根目录下,大约有100MB。测试方法很简单,每次读取32KB的文件内容,连续请求200次,最后获取消耗的时间。
78+
79+
```text
80+
I (1709) micro_storage: [Sync] Read 13107200 bytes in 1.593215s
81+
...
82+
I (21727) micro_storage: [Async] Read 13107200 bytes in 4.229245s
83+
```
84+
85+
我共测试了两次,第一次使用同步接口,第二次使用了tokio库的异步接口。使用异步接口后同样的任务时间却增加了2.6秒,大概由于只有一个并发请求,增加了开销但没有带来收益。但增加的时延具体耗费在哪些事情上了,还需要进一步分析。对于ESP32这样的资源受限的平台,使用异步编程接口可能是”杀鸡用了牛刀“。同步读的速度约为7.9MB/秒,异步读的速度约为3.0MB/秒。
86+
87+
88+
### 测试顺序写速度
89+
90+
测试顺序写速度使用了和测试顺序读类似的方法。而且也测试了一次同步接口和一次异步接口。
91+
92+
```Rust
93+
async fn test_wfile_perf(mount_point: &str) -> anyhow::Result<()> {
94+
let file_path = format!("{}/wfile_async.bin", mount_point);
95+
96+
tokio::task::spawn(async move {
97+
let mut file = tokio::fs::File::create(file_path).await?;
98+
let mut write_buf = std::vec![0xfu8;32*1024];
99+
let mut write_size: usize = 0;
100+
101+
let beg = tokio::time::Instant::now();
102+
103+
for _i in 0..400 {
104+
let size = file.write(&mut write_buf).await?;
105+
write_size += size;
106+
}
107+
108+
info!("[Async] Write {} bytes in {:?}", write_size, beg.elapsed());
109+
110+
Ok::<_, anyhow::Error>(())
111+
}).await?
112+
}
113+
114+
fn test_wfile_sync(mount_point: &str) -> anyhow::Result<()> {
115+
let file_path = format!("{}/wfile_sync.bin", mount_point);
116+
let mut file = std::fs::File::create(file_path)?;
117+
let mut write_buf = std::vec![3u8;32*1024];
118+
let mut write_size: usize = 0;
119+
120+
let beg = tokio::time::Instant::now();
121+
122+
use std::io::Write;
123+
for _i in 0..400 {
124+
let size = file.write(&mut write_buf).unwrap();
125+
write_size += size;
126+
}
127+
128+
info!("[Sync] Write {} bytes in {:?}", write_size, beg.elapsed());
129+
130+
Ok::<_, anyhow::Error>(())
131+
}
132+
```
133+
134+
测试结果如下。经过计算同步写的速度大约为3MB/秒,而异步写速度只有1.8MB/秒。
135+
136+
```text
137+
I (6263) micro_storage: [Sync] Write 13107200 bytes in 4.11604s
138+
...
139+
I (29223) micro_storage: [Async] Write 13107200 bytes in 7.079895s
140+
```
141+
142+
143+
## 总结
144+
145+
我们得到同步顺序读写的速度为7.9MB/秒和3MB/秒,异步接口的顺序读写性能要差一些,为3MB/秒和1.8MB/秒。前一对数字还差强人意,后一对数字就有点难看了。但是我们的WebDAV程序正是使用的异步接口,所以读写性能不会太好。本来想实际测试WebDAV程序的下载和上传性能,但是因为系统经常报告内存不够,导致系统OOM。虽然我的ESP32S3模块有8MB的SPIRAM,但是我发现启用了SPIRAM之后,会出现无法挂载TF卡的错误,我怀疑是硬件设计的问题,所以展示无法对性能进行端到端测试。
146+
147+
148+
## 链接
149+
150+
1. esp\_webdav - <https://github.com/paul356/esp-webdav>

0 commit comments

Comments
 (0)