Comments (20)
I'm on vacation right now but the weather is even worse than it was the other days - so I took my gaming laptop and an ESP32-C3 and had a look.
I took the DHCP example and just changed the fetched URL, then added printing the duration and bytes downloaded - I got around 14000 bytes/second. Pretty bad.
Changing the socket buffer and similar simple things got me to around 37000 bytes/second. Still not good.
I tried a few things in esp-wifi
itself and changed to my laptop as the HTTP server.
Bytes 1863616, millis 3012, B/s 618730
Making HTTP request
Bytes 1863616, millis 2402, B/s 775860
Making HTTP request
Bytes 1863616, millis 4666, B/s 399403
Making HTTP request
Bytes 1863616, millis 3909, B/s 476750
Making HTTP request
Bytes 1863616, millis 2976, B/s 626215
Making HTTP request
Bytes 1863616, millis 3072, B/s 606645
Making HTTP request
Bytes 1863616, millis 4665, B/s 399488
Making HTTP request
Bytes 1863616, millis 3537, B/s 526891
Making HTTP request
Bytes 1863616, millis 4241, B/s 439428
Making HTTP request
Bytes 1863616, millis 3956, B/s 471085
Making HTTP request
Bytes 1863616, millis 3149, B/s 591812
Making HTTP request
Bytes 1863616, millis 4226, B/s 440988
Making HTTP request
Bytes 1863616, millis 3338, B/s 558303
Making HTTP request
While the speed varies a lot (probably due to my crap access-point and the device not sitting exactly next to the AP) this is much better.
Unfortunately, the changes are not in a shape that I can just make it a PR yet - will do that after my vacation since I also need to check a few things (e.g. increased memory usage, how it affects other chips).
However, I think these numbers are quite promising.
from esp-wifi.
With #233 it will be possible to configure various internals which got me much better performance. Finding the best values might be a trial-and-error thing however
from esp-wifi.
@bjoernQ do you happen to remember what settings were effective during your july trial?
I think it was like this
rx_queue_size = 20
tx_queue_size = 5
static_rx_buf_num = 32
dynamic_rx_buf_num = 16
ampdu_rx_enable = 1
ampdu_tx_enable = 1
rx_ba_win = 32
max_burst_size = 8
from esp-wifi.
IIRC @MabezDev did some tests and the results where much, much better than your results. t.b.h. I haven't benchmarked it myself
Maybe worth to try this with a different client (e.g. another PC) and see if what the WiFI and the server can do - just to rule that out
from esp-wifi.
i ruled out weak wifi connection by moving esp close to router. I'm using https://github.com/dheijl/swyh-rs as audio source, so i think i should be fine. I'll try to make some simple rust client to try the speed on my laptop, but maybe somebody will notice some configuration or other errors in my code.
from esp-wifi.
I also had the same problem the last two days. I wrote multiple benchmarks for download speeds. The code used is available here. Here is the result I got (on my PC I get speeds up to 25 MB/s on Wi-Fi, so the Wi-Fi is plenty fast):
It seems that there is a bottleneck somewhere, as the download speed is very similar across download sizes. The esp32-s3, which I tested on, should be capable of 2.5 MB/s (20 Mbit/s).
from esp-wifi.
I tried downloading file from http://speedtest.ftp.otenet.gr/files/test10Mb.db
(which on my PC in Firefox browser clocks at > 1 MiB/s) and i get only about 10 KiB/s on esp32c3.
from esp-wifi.
IIRC @MabezDev did some tests and the results where much, much better than your results. t.b.h. I haven't benchmarked it myself
Is it possible to get code for those benchmarks that @MabezDev did ? Maybe that will point me to some errors in my code.
from esp-wifi.
@bjoernQ do you happen to remember what settings were effective during your july trial?
from esp-wifi.
FWIW the best I could achieve is still an order of magnitude slower than yours.
Average speed: 34.3kB/s KiB/s
I'm not blocked on my display, I'm not bottlenecked by TLS (yet), this speed is the same with/without HTTPS. Did you happen to have some other modifications privately that didn't get into esp-wifi by any chance? :)
from esp-wifi.
IIRC it was really just what is also in the tuning document. But I also had to use large receive and socket buffers to get there - I can try to reproduce it when I'm back home (next week)
from esp-wifi.
Changing the buffer size may be a good idea. There are some details in my firmware that make it difficult to test right now but I'll try and play with it some.
Update: I wasn't able to achieve much by upping my socket buffer from 4k to 32k. Some improvement, ~10-15% on average.
from esp-wifi.
Using this code with merged #233 :
Code
``` #![no_std]
#![no_main]
#[path = "../../examples-util/util.rs"]
mod examples_util;
use examples_util::hal;
use embedded_io::blocking::*;
use embedded_svc::ipv4::Interface;
use embedded_svc::wifi::{AccessPointInfo, ClientConfiguration, Configuration, Wifi};
use esp_backtrace as _;
use esp_println::{print, println};
use esp_wifi::wifi::utils::create_network_interface;
use esp_wifi::wifi::{WifiError, WifiMode};
use esp_wifi::wifi_interface::WifiStack;
use esp_wifi::{current_millis, initialize, EspWifiInitFor};
use hal::clock::ClockControl;
use hal::{peripherals::Peripherals, prelude::*};
use hal::{systimer::SystemTimer, Rng};
use smoltcp::iface::SocketStorage;
use smoltcp::wire::IpAddress;
use smoltcp::wire::Ipv4Address;
const SSID: &str = env!("SSID");
const PASSWORD: &str = env!("PASSWORD");
#[entry]
fn main() -> ! {
#[cfg(feature = "log")]
esp_println::logger::init_logger(log::LevelFilter::Info);
let peripherals = Peripherals::take();
let system = peripherals.SYSTEM.split();
let clocks = ClockControl::max(system.clock_control).freeze();
let timer = SystemTimer::new(peripherals.SYSTIMER).alarm0;
let init = initialize(
EspWifiInitFor::Wifi,
timer,
Rng::new(peripherals.RNG),
system.radio_clock_control,
&clocks,
)
.unwrap();
let (wifi, ..) = peripherals.RADIO.split();
let mut socket_set_entries: [SocketStorage; 3] = Default::default();
let (iface, device, mut controller, sockets) =
create_network_interface(&init, wifi, WifiMode::Sta, &mut socket_set_entries).unwrap();
let wifi_stack = WifiStack::new(iface, device, sockets, current_millis);
let client_config = Configuration::Client(ClientConfiguration {
ssid: SSID.into(),
password: PASSWORD.into(),
..Default::default()
});
let res = controller.set_configuration(&client_config);
println!("wifi_set_configuration returned {:?}", res);
controller.start().unwrap();
println!("is wifi started: {:?}", controller.is_started());
println!("Start Wifi Scan");
let res: Result<(heapless::Vec<AccessPointInfo, 10>, usize), WifiError> = controller.scan_n();
if let Ok((res, _count)) = res {
for ap in res {
println!("{:?}", ap);
}
}
println!("{:?}", controller.get_capabilities());
println!("wifi_connect {:?}", controller.connect());
// wait to get connected
println!("Wait to get connected");
loop {
let res = controller.is_connected();
match res {
Ok(connected) => {
if connected {
break;
}
}
Err(err) => {
println!("{:?}", err);
loop {}
}
}
}
println!("{:?}", controller.is_connected());
// wait for getting an ip address
println!("Wait to get an ip address");
loop {
wifi_stack.work();
if wifi_stack.is_iface_up() {
println!("got ip {:?}", wifi_stack.get_ip_info());
break;
}
}
println!("Start busy loop on main");
let mut rx_buffer = [0u8; 1536 * 64];
let mut tx_buffer = [0u8; 1536 * 1];
let mut socket = wifi_stack.get_socket(&mut rx_buffer, &mut tx_buffer);
let mut current_try = 1;
let max_tries = 3;
let mut speed_sum = 0;
loop {
println!("Making HTTP request (count {})", current_try);
socket.work();
socket
.open(IpAddress::Ipv4(Ipv4Address::new(10, 1, 1, 10)), 80)
.unwrap();
socket
.write(b"GET /testfile HTTP/1.0\r\nHost: 10.1.1.10\r\n\r\n")
.unwrap();
socket.flush().unwrap();
let wait_end = current_millis() + 20 * 1000;
let mut bytes = 0;
let t1 = current_millis();
let mut buffer = [0u8; 1024 * 32];
loop {
if let Ok(len) = socket.read(&mut buffer) {
//println!("{len}");
bytes += len;
} else {
break;
}
if current_millis() > wait_end {
println!("Timeout");
break;
}
}
let t2 = current_millis();
println!();
socket.disconnect();
let speed = bytes as u64 * 1000 / (t2 as u64 - t1 as u64);
println!("Bytes {}, millis {}, B/s {}", bytes, t2 - t1, speed);
speed_sum += speed;
let wait_end = current_millis() + 5 * 1000;
while current_millis() < wait_end {
socket.work();
}
current_try += 1;
if current_try > max_tries {
let avg_speed = speed_sum / max_tries;
println!("Avg speed in {} tries {} B/s", max_tries, avg_speed);
loop {
}
}
}
}
```
I've used those values for experiments:
test | rx_queue_size | tx_queue_size | static_rx_buf_num | dynamic_rx_buf_num | static_tx_buf_num | dynamic_tx_buf_num | ampdu_rx_enable | ampdu_tx_enable | rx_ba_win | max_burst_size | country_code |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | 5 | 3 | 10 | 32 | 0 | 32 | 0 | 0 | 6 | 1 | CN |
2 | 20 | 5 | 32 | 16 | 16 | 16 | 1 | 1 | 32 | 8 | PL |
And those were the results:
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | ||
---|---|---|---|---|---|---|---|---|---|---|---|---|
test | speed B/s (avg of 3) | rx_queue_size | tx_queue_size | static_rx_buf_num | dynamic_rx_buf_num | static_tx_buf_num | dynamic_tx_buf_num | ampdu_rx_enable | ampdu_tx_enable | rx_ba_win | max_burst_size | country_code |
1 | 124764 | 5 | 3 | 10 | 32 | 0 | 32 | 0 | 0 | 6 | 1 | CN |
2 | 60115 | 5 | 3 | 10 | 32 | 0 | 16 | 1 | 1 | 32 | 8 | PL |
3 | 63889 | 5 | 3 | 32 | 16 | 16 | 32 | 0 | 0 | 32 | 8 | PL |
4 | 114179 | 5 | 5 | 10 | 16 | 16 | 32 | 1 | 1 | 6 | 1 | PL |
5 | 65398 | 5 | 5 | 32 | 32 | 16 | 16 | 0 | 1 | 6 | 8 | CN |
6 | 133764 | 5 | 5 | 32 | 16 | 0 | 16 | 1 | 0 | 32 | 1 | CN |
7 | 407828 | 20 | 3 | 32 | 16 | 0 | 32 | 1 | 1 | 6 | 8 | CN |
8 | 113233 | 20 | 3 | 32 | 32 | 16 | 16 | 1 | 0 | 6 | 1 | PL |
9 | 114566 | 20 | 3 | 10 | 16 | 16 | 16 | 0 | 1 | 32 | 1 | CN |
10 | 116413 | 20 | 5 | 32 | 32 | 0 | 32 | 0 | 1 | 32 | 1 | PL |
11 | 435955 | 20 | 5 | 10 | 16 | 0 | 16 | 0 | 0 | 6 | 8 | PL |
12 | 328365 | 20 | 5 | 10 | 32 | 16 | 32 | 1 | 0 | 32 | 8 | CN |
SUM 1 | 562109 | 884395 | 1177944 | 808288 | 1278839 | 1155438 | 920985 | 1199970 | 1261357 | 716919 | 1174685 | |
SUM 2 | 1516360 | 1194074 | 900525 | 1270181 | 799630 | 923031 | 1157484 | 878499 | 817112 | 1361550 | 903784 |
Unfortunately i live in very RF noisy place, so i couldn't rule out external variables, but i think this method can lead to even better results.
from esp-wifi.
I have been testing esp32s3 with an ambition to push ~2.5MB/s over TCP from the board; the most I was able to get from esp-wifi was 300kBytes/s, achieved mostly due to larger smoltcp buffer. To put in in perspective, though, the C iperf example from esp-idf, achieves 5-5.5 MBytes/s.
The board config reads:
#
# ESP32S3-specific
#
CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=16
CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=64
CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM=64
CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP_WIFI_TX_BA_WIN=32
CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP_WIFI_RX_BA_WIN=32
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=65535
CONFIG_LWIP_TCP_WND_DEFAULT=65535
CONFIG_LWIP_TCP_RECVMBOX_SIZE=64
CONFIG_LWIP_UDP_RECVMBOX_SIZE=64
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=64
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB=y
CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y
CONFIG_ESP32S3_INSTRUCTION_CACHE_WRAP=y
So it seems that the secret ingredients are increasing the flash read speed and bumping up the ICACHE... Is there a way to change them in a no-std Rust stack?
from esp-wifi.
So it seems that the secret ingredients are increasing the flash read speed and bumping up the ICACHE... Is there a way to change them in a no-std Rust stack?
Those things are currently not configurable in esp-hal. While it will make a difference, I think it needs more since 300k vs 5M is a huge difference. Can you post your cfg.toml
?
from esp-wifi.
Sure:
[esp-wifi]
rx_queue_size = 3
tx_queue_size = 3
static_rx_buf_num = 16
dynamic_rx_buf_num = 16
static_tx_buf_num=16
dynamic_tx_buf_num=16
ampdu_rx_enable = 1
ampdu_tx_enable = 1
country_code="PL"
rx_ba_win = 32
tx_ba_win = 32
max_burst_size = 8
EspHeap is 100 kib, RX buffer 1 kib (since its only for ACKs), TX buffer is 64 kib, to mirror ESP config. It would benefit from larger queues since it emits a lot of "no TX token" warnings, but it seem to OOM if it is increased (I'm very new to ESP32 and its memory layout so I'm likely doing something stupid, though).
I'm going to test how disabling flash/cache in sdkconfig hurts the idf demo, this should give us a hint how useful they are.
from esp-wifi.
I was not able to run the iperf example with modified parameters (this fancy pseudo-shell got broken easier than wifi), yet I made a simple project with esp-idf stack pushing 1KiB of static data in a blocking way. I have used the following sdkconfig.defaults
file:
##--- This part is from Rust template ---
# Rust often needs a bit of an extra main task stack size compared to C (the default is 3K)
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8000
# Use this to set FreeRTOS kernel tick frequency to 1000 Hz (100 Hz by default).
# This allows to use 1 ms granuality for thread sleeps (10 ms by default).
#CONFIG_FREERTOS_HZ=1000
# Workaround for https://github.com/espressif/esp-idf/issues/7631
#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE=n
#CONFIG_MBEDTLS_CERTIFICATE_BUNDLE_DEFAULT_FULL=n
##--- This is the IPERF demo config ---
## -- The Modem/LWIP part --
CONFIG_ESP_WIFI_STATIC_RX_BUFFER_NUM=16
CONFIG_ESP_WIFI_DYNAMIC_RX_BUFFER_NUM=64
CONFIG_ESP_WIFI_DYNAMIC_TX_BUFFER_NUM=64
CONFIG_ESP_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP_WIFI_TX_BA_WIN=32
CONFIG_ESP_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP_WIFI_RX_BA_WIN=32
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=65535
CONFIG_LWIP_TCP_WND_DEFAULT=65535
CONFIG_LWIP_TCP_RECVMBOX_SIZE=64
CONFIG_LWIP_UDP_RECVMBOX_SIZE=64
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=64
## -- The Cpufreq part --
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240
## -- The QIO (flash speed) part --
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
## -- The ICACHE part --
CONFIG_ESP32S3_INSTRUCTION_CACHE_32KB=y
CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B=y
CONFIG_ESP32S3_INSTRUCTION_CACHE_WRAP=y
It has three blocks that I was then turning on/off; here are my results (def
means defaults/block off, iperf
means settings from the demo):
Modem/LWIP | CPU Freq | QIO+Flash | ICACHE | Speed |
---|---|---|---|---|
def | 160MHz | def | def | 643KiB/s |
iperf | 240MHz | iperf | iperf | 3.62MiB/s |
iperf | 240MHz | def | iperf | 3.62MiB/s |
iperf | 240MHz | def | def | 879KiB/s |
def | 160MHz | def | iperf | 1.69MiB/s |
def | 240MHz | iperf | iperf | 2.06MiB/s |
It is pretty evident that instruction cache is a main source of speed-up; playing with buffers and queue sizes helps, but I doubt it can get one over the 1MiBps barrier.
from esp-wifi.
You could try playing with patching various values from here: https://github.com/esp-rs/esp-hal/blob/4d87e75d71b55d546b37aff6a4494cefb743c4a9/esp32s3-hal/src/lib.rs#L76-L100 in esp-hal. We have a longer-standing issue around cache configuration here: esp-rs/esp-hal#955.
Edit: for the other chips, I believe the cache settings can be configured in the bootloader and they will persist to the main app, so we may be able to get some speed up on other chips too.
Another factor is that xtensa-lx-rt curren't can't do lazy loading of float registers (maybe we should just put it behind a feature?) so that will affect the context switch performance greatly.
from esp-wifi.
@mbq you may wish to test with #430, on RISCV at least I was seeing 2MB/s upload speeds. It seems there are still some bottlenecks on Xtensa though.
from esp-wifi.
@MabezDev For a fast test I tried bumping esp-wifi to main, and the result was 50% throughput drop, from 313KiB/s to 139KiB/s (this is on S3 board with a sync code that just tries to push as many bytes as possible); I haven't tested cache patches yet.
Anyhow, I decided to use IDF for the project I'm doing now, but I'm still keeping my fingers crossed for a solution here.
from esp-wifi.
Related Issues (20)
- esp-wifi 0.3.0 does not compile for ESP32-C3, it depends on portable-atomic, and that doesnt build for RiscV HOT 5
- How to depend on esp-wifi in an external example HOT 3
- Long async ping time when idle HOT 3
- example/embassy_ble does not compile HOT 2
- esp-wifi lockup on esp32c3 when using the embassy InterruptExecutor HOT 3
- multiple definition of malloc, calloc, and free when used together with other crates providing them HOT 3
- [ESP32] esp-wifi crashes when trying to connect via BLE HOT 6
- NVS initialization error HOT 1
- ps-min-modem / ps-max-modem not working on esp32c3 HOT 2
- Blocking socket API need to implement `ReadReady` / `WriteReady`
- compile error HOT 2
- W (42148) wifi:m f null Getting This warning and then wifi is never reconnected in the execution HOT 1
- esp32c6 uses only password while config AuthMethod:None HOT 3
- Example code for my c6 chip has no println output
- Critical section feature conflict between esp-wifi and esp-idf-hal HOT 3
- #[interrupt] macro has been removed from esp-hal-procmacros HOT 6
- H2: Don't try to use `phy_bbpll_en_usb` HOT 1
- docs.rs failed to build HOT 3
- HTTPS support HOT 2
- [RISCV] Stable esp-wifi HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from esp-wifi.