fix: move http upload state to heap (#657)

## Summary

The main motivation behind this PR was because `uploadBuffer` is
statically allocated, but only used when web server is enabled. This
results in 4KB of memory sitting idle most of the time.

As expected, 4KB of initial RAM is freed with this PR:

```
master:
RAM:   [===       ]  32.5% (used 106508 bytes from 327680 bytes)

PR:
RAM:   [===       ]  31.2% (used 102276 bytes from 327680 bytes)
```

## Additional Context

This also highlights the importance of only using statically-allocated
buffer when absolutely needed (for example, if the component is active
most of the time). Otherwise, it makes more sense to tie the buffer's
life cycle to its activity.

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? NO
This commit is contained in:
Xuan-Son Nguyen
2026-02-05 11:03:19 +01:00
committed by GitHub
parent 78d6e5931c
commit db659f3ea2
2 changed files with 81 additions and 76 deletions

View File

@@ -1,5 +1,6 @@
#pragma once
#include <SDCardManager.h>
#include <WebServer.h>
#include <WebSocketsServer.h>
#include <WiFiUdp.h>
@@ -28,6 +29,25 @@ class CrossPointWebServer {
unsigned long lastCompleteAt = 0;
};
// Used by POST upload handler
struct UploadState {
FsFile file;
String fileName;
String path = "/";
size_t size = 0;
bool success = false;
String error = "";
// Upload write buffer - batches small writes into larger SD card operations
// 4KB is a good balance: large enough to reduce syscall overhead, small enough
// to keep individual write times short and avoid watchdog issues
static constexpr size_t UPLOAD_BUFFER_SIZE = 4096; // 4KB buffer
std::vector<uint8_t> buffer;
size_t bufferPos = 0;
UploadState() { buffer.resize(UPLOAD_BUFFER_SIZE); }
} upload;
CrossPointWebServer();
~CrossPointWebServer();
@@ -74,8 +94,8 @@ class CrossPointWebServer {
void handleFileList() const;
void handleFileListData() const;
void handleDownload() const;
void handleUpload() const;
void handleUploadPost() const;
void handleUpload(UploadState& state) const;
void handleUploadPost(UploadState& state) const;
void handleCreateFolder() const;
void handleDelete() const;
};