Memory Optimizations
This commit is contained in:
238
MEMORY_OPTIMIZATIONS_WEB.md
Normal file
238
MEMORY_OPTIMIZATIONS_WEB.md
Normal file
@@ -0,0 +1,238 @@
|
||||
# ESP32 MP3 Player - Web Request & WiFiManager Memory Optimizations
|
||||
|
||||
## High-Impact Web Request Optimizations
|
||||
|
||||
### 1. **ESPAsyncWifiManager Configuration Optimization** (HIGH IMPACT: 10-20KB)
|
||||
|
||||
The ESPAsyncWifiManager can be configured to use less memory:
|
||||
|
||||
```cpp
|
||||
// In setup(), before wifiManager.autoConnect():
|
||||
AsyncWiFiManager wifiManager(&server, &dns);
|
||||
|
||||
// Reduce timeout to free memory faster
|
||||
wifiManager.setTimeout(60); // Reduced from 180 to 60 seconds
|
||||
|
||||
// Disable debug output to save memory
|
||||
wifiManager.setDebugOutput(false);
|
||||
|
||||
// Set custom parameters to reduce memory usage
|
||||
wifiManager.setConfigPortalBlocking(false); // Non-blocking mode saves memory
|
||||
wifiManager.setConnectTimeout(20); // Faster connection timeout
|
||||
wifiManager.setConfigPortalTimeout(60); // Shorter portal timeout
|
||||
```
|
||||
|
||||
### 2. **Web Server Request Handler Optimization** (MEDIUM IMPACT: 5-10KB)
|
||||
|
||||
Current issue: Each request handler creates temporary objects and strings.
|
||||
|
||||
**Optimization A: Use String References Instead of Copies**
|
||||
```cpp
|
||||
// Replace current parameter handling with more efficient version:
|
||||
void id_song_action(AsyncWebServerRequest *request)
|
||||
{
|
||||
const AsyncWebParameter* p = request->getParam("id");
|
||||
if (p != nullptr) {
|
||||
playSongById(p->value().toInt()); // Direct conversion, no string copy
|
||||
}
|
||||
lastInteraction = millis();
|
||||
request->send_P(200, "text/plain", "ok"); // Use PROGMEM string
|
||||
}
|
||||
```
|
||||
|
||||
**Optimization B: Reduce JSON Buffer Allocations**
|
||||
```cpp
|
||||
String getState()
|
||||
{
|
||||
// Use static buffer to avoid repeated allocations
|
||||
static DynamicJsonDocument jsonState(384); // Further reduced from 512
|
||||
jsonState.clear(); // Clear previous data
|
||||
|
||||
jsonState[F("playing")] = audio.isRunning(); // Use F() macro
|
||||
|
||||
if (currentNode != nullptr)
|
||||
jsonState[F("title")] = *currentNode->getCurrentPlaying();
|
||||
else
|
||||
jsonState[F("title")] = F("Angehalten"); // Store in flash
|
||||
|
||||
jsonState[F("time")] = audio.getAudioCurrentTime();
|
||||
jsonState[F("volume")] = audio.getVolume();
|
||||
jsonState[F("length")] = audio.getAudioFileDuration();
|
||||
jsonState[F("voltage")] = lastVoltage;
|
||||
jsonState[F("uid")] = lastUid;
|
||||
jsonState[F("heap")] = free_heap;
|
||||
|
||||
String output;
|
||||
output.reserve(256); // Pre-allocate string buffer
|
||||
serializeJson(jsonState, output);
|
||||
return output;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. **File Upload Handler Memory Optimization** (HIGH IMPACT: 15-30KB)
|
||||
|
||||
Current issue: Large temporary buffers and inefficient string operations.
|
||||
|
||||
```cpp
|
||||
void handleUpload(AsyncWebServerRequest *request, String filename, size_t index, uint8_t *data, size_t len, bool final) {
|
||||
static String logBuffer; // Static to avoid repeated allocations
|
||||
|
||||
if (!index) {
|
||||
// Use const references to avoid string copies
|
||||
const String& lowerFilename = filename;
|
||||
|
||||
// Pre-allocate log buffer
|
||||
logBuffer.reserve(128);
|
||||
logBuffer = F("Upload Start: ");
|
||||
logBuffer += filename;
|
||||
|
||||
// More efficient space check
|
||||
uint32_t freeSpace = (SD.cardSize() - SD.usedBytes()) >> 20; // Bit shift instead of division
|
||||
|
||||
if (freeSpace < 10) {
|
||||
request->send(507, F("text/plain"), F("Insufficient storage space"));
|
||||
return;
|
||||
}
|
||||
|
||||
Serial.println(logBuffer);
|
||||
logBuffer.clear(); // Free memory immediately
|
||||
|
||||
// ... rest of upload logic
|
||||
}
|
||||
|
||||
// Reduce logging frequency to save memory
|
||||
if (len && (index % 204800 == 0)) { // Log every 200KB instead of 100KB
|
||||
logBuffer = F("Upload: ");
|
||||
logBuffer += humanReadableSize(index + len);
|
||||
Serial.println(logBuffer);
|
||||
logBuffer.clear();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 4. **HTML Template Processing Optimization** (MEDIUM IMPACT: 3-5KB)
|
||||
|
||||
```cpp
|
||||
String processor(const String &var)
|
||||
{
|
||||
if (var == F("DIRECTORY")) // Use F() macro
|
||||
{
|
||||
return rootNode.getDirectoryStructureHTML();
|
||||
}
|
||||
return String(); // Return empty string instead of creating new String
|
||||
}
|
||||
```
|
||||
|
||||
### 5. **Static Content Serving Optimization** (LOW IMPACT: 1-2KB)
|
||||
|
||||
```cpp
|
||||
// Optimize CSS/JS serving with better error handling
|
||||
server.on("/style.css", HTTP_GET, [](AsyncWebServerRequest *request) {
|
||||
activateSD();
|
||||
const char* cssPath = "/system/style.css";
|
||||
if (SD.exists(cssPath)) {
|
||||
request->send(SD, cssPath, F("text/css"));
|
||||
} else {
|
||||
// Serve minimal fallback without creating large strings
|
||||
request->send_P(200, "text/css", "body{font-family:Arial;text-align:center;}");
|
||||
}
|
||||
deactivateSD();
|
||||
});
|
||||
```
|
||||
|
||||
## ESPAsyncWifiManager Specific Optimizations
|
||||
|
||||
### 6. **WiFiManager Memory Pool Configuration** (HIGH IMPACT: 15-25KB)
|
||||
|
||||
```cpp
|
||||
// Add these configurations in setup():
|
||||
void setup() {
|
||||
// ... existing code ...
|
||||
|
||||
AsyncWiFiManager wifiManager(&server, &dns);
|
||||
|
||||
// Memory optimizations for WiFiManager
|
||||
wifiManager.setDebugOutput(false); // Disable debug strings
|
||||
wifiManager.setMinimumSignalQuality(20); // Reduce AP scan results
|
||||
wifiManager.setRemoveDuplicateAPs(true); // Remove duplicate APs from memory
|
||||
wifiManager.setConfigPortalBlocking(false); // Non-blocking saves memory
|
||||
wifiManager.setScanDisposeDelay(5000); // Dispose scan results faster
|
||||
|
||||
// Reduce timeouts to free memory faster
|
||||
wifiManager.setTimeout(60); // Reduced from 180
|
||||
wifiManager.setConnectTimeout(15); // Faster connection attempts
|
||||
wifiManager.setConfigPortalTimeout(60); // Shorter portal timeout
|
||||
|
||||
// Custom CSS/HTML to reduce memory usage (optional)
|
||||
wifiManager.setCustomHeadElement(F("<style>body{font-size:14px;}</style>"));
|
||||
|
||||
if (wifiManager.autoConnect("HannaBox")) {
|
||||
// ... existing server setup ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Additional Compiler & Build Optimizations
|
||||
|
||||
### 7. **Enhanced Build Flags** (MEDIUM IMPACT: 5-10KB)
|
||||
|
||||
Add to `platformio.ini`:
|
||||
```ini
|
||||
build_flags =
|
||||
-Os ; Optimize for size
|
||||
-DCORE_DEBUG_LEVEL=0 ; Disable all debug output
|
||||
-DARDUINO_LOOP_STACK_SIZE=3072 ; Further reduce from 4096
|
||||
-DWIFI_TASK_STACK_SIZE=3072 ; Reduce WiFi task stack
|
||||
-DARDUINO_EVENT_TASK_STACK_SIZE=2048 ; Reduce event task stack
|
||||
-DTCPIP_TASK_STACK_SIZE=2048 ; Reduce TCP/IP stack
|
||||
-DESP_TASK_WDT_TIMEOUT_S=10 ; Reduce watchdog timeout
|
||||
-DCONFIG_ASYNC_TCP_MAX_ACK_TIME=3000 ; Reduce TCP ACK timeout
|
||||
-DCONFIG_ASYNC_TCP_QUEUE_SIZE=32 ; Reduce TCP queue size
|
||||
```
|
||||
|
||||
## Implementation Priority
|
||||
|
||||
1. **IMMEDIATE (High Impact)**:
|
||||
- ESPAsyncWifiManager configuration optimization
|
||||
- File upload handler memory optimization
|
||||
- Enhanced build flags
|
||||
|
||||
2. **SHORT TERM (Medium Impact)**:
|
||||
- JSON buffer optimization with F() macros
|
||||
- Web request handler optimization
|
||||
- Static content serving optimization
|
||||
|
||||
3. **LONG TERM (Maintenance)**:
|
||||
- Monitor memory usage patterns
|
||||
- Consider implementing request queuing if needed
|
||||
- Profile actual memory usage during web operations
|
||||
|
||||
## Expected Total Memory Savings
|
||||
|
||||
| Optimization Category | Memory Saved |
|
||||
|----------------------|--------------|
|
||||
| ESPAsyncWifiManager Config | 15-25KB |
|
||||
| File Upload Handler | 15-30KB |
|
||||
| JSON & String Optimizations | 5-10KB |
|
||||
| Build Flag Optimizations | 5-10KB |
|
||||
| **Total Potential Savings** | **40-75KB** |
|
||||
|
||||
## Testing & Validation
|
||||
|
||||
After implementing these optimizations:
|
||||
|
||||
1. Monitor free heap via web interface during:
|
||||
- WiFi connection process
|
||||
- File uploads
|
||||
- Multiple concurrent web requests
|
||||
- JSON state requests
|
||||
|
||||
2. Test stability under load:
|
||||
- Multiple rapid web requests
|
||||
- Large file uploads
|
||||
- WiFi reconnection scenarios
|
||||
|
||||
3. Verify functionality:
|
||||
- All web endpoints work correctly
|
||||
- File uploads complete successfully
|
||||
- WiFi manager portal functions properly
|
||||
Reference in New Issue
Block a user