Skip to content

Instantly share code, notes, and snippets.

@ciniml
Created November 28, 2020 22:06
Show Gist options
  • Save ciniml/6cd9dc15e58d9b3ab2abae65a6873ce4 to your computer and use it in GitHub Desktop.
Save ciniml/6cd9dc15e58d9b3ab2abae65a6873ce4 to your computer and use it in GitHub Desktop.
M5Paper Storage Benchmark
#include <M5EPD.h>
#include <Free_Fonts.h>
#include <WiFi.h>
#include <lwip/sockets.h>
#include <lwip/netdb.h>
#include <cstdio>
#include <cstdlib>
#include <cstdint>
#include <cstring>
#include <memory>
#include <array>
#include <cstdarg>
#include <SPIFFS.h>
#include <SD.h>
#include <esp_spi_flash.h>
#define TFCARD_CS_PIN 4
class CBFSBench
{
public:
String tmpFile{"/lovyanLauncherBench"};
virtual const char* name() = 0;
uint64_t getWriteTime(fs::FS& fs, const String& filepath, long filesize, int loop) volatile {
File f;
uint64_t res = 0;
uint8_t buf[SPI_FLASH_SEC_SIZE];
for (int i = 0; i < SPI_FLASH_SEC_SIZE; ++i) { buf[i] = uint8_t(i & 0xFF); }
for (int i = 0; i < loop; ++i) {
long rest = filesize;
uint64_t start = micros();
f = fs.open(filepath + String(i), FILE_WRITE);
do {
long size = rest > SPI_FLASH_SEC_SIZE ? SPI_FLASH_SEC_SIZE : rest;
f.write(&buf[0], size);
rest -= size;
} while (rest > 0);
f.flush();
f.close();
res += micros() - start;
}
return res / loop;
}
uint64_t getReadTime(fs::FS& fs, const String& filepath, long filesize, int loop) volatile {
File f;
uint64_t res = 0;
uint8_t buf[SPI_FLASH_SEC_SIZE];
for ( int i = 0; i < loop; ++i) {
long rest = filesize;
uint64_t start = micros();
f = fs.open(filepath + String(i), FILE_READ);
do {
long size = rest > SPI_FLASH_SEC_SIZE ? SPI_FLASH_SEC_SIZE : rest;
f.read(&buf[0], size);
rest -= size;
} while (rest > 0);
f.close();
res += micros() - start;
fs.remove(filepath + String(i));
}
return res / loop;
}
uint64_t getCreateTime(fs::FS& fs, const String& filepath, int loop) volatile {
uint64_t start = micros();
for ( int i = 0; i < loop; ++i) {
fs.open(filepath + String(i), FILE_WRITE).close();
}
return (micros() - start) / loop;
}
uint64_t getOpenCloseTime(fs::FS& fs, const String& filepath, int loop) volatile {
uint64_t start = micros();
for ( int i = 0; i < loop; ++i) {
fs.open(filepath + String(i), FILE_READ).close();
}
return (micros() - start) / loop;
}
uint64_t getRemoveTime(fs::FS& fs, const String& filepath, int loop) volatile {
uint64_t start = micros();
for (int i = 0; i < loop; ++i) {
fs.remove(filepath + String(i));
}
return (micros() - start) / loop;
}
virtual fs::FS& getFS() = 0;
virtual void init() = 0;
virtual uint64_t totalBytes() { return 0; }
virtual uint64_t usedBytes() { return 0; }
};
class CBFSBenchSD : public CBFSBench
{
const char* name() { return "SD"; }
fs::FS& getFS() override { return SD; }
uint64_t totalBytes() override { return SD.totalBytes(); }
uint64_t usedBytes() override { return SD.usedBytes(); }
void init() override
{
SD.end();
SD.begin( TFCARD_CS_PIN, SPI, 40000000);
}
};
class CBFSBenchSPIFFS : public CBFSBench
{
const char* name() { return "SPIFFS"; }
fs::FS& getFS() override { return SPIFFS; }
uint64_t totalBytes() override{ return SPIFFS.totalBytes(); }
uint64_t usedBytes() override { return SPIFFS.usedBytes(); }
void init() override
{
SPIFFS.begin(true);
}
};
static CBFSBenchSD bench_sd;
static CBFSBenchSPIFFS bench_spiffs;
static CBFSBench* const benches[] = {&bench_sd, &bench_spiffs};
struct ReadWriteResult
{
std::uint64_t read_time;
std::uint64_t write_time;
std::uint64_t size_in_kib;
};
static void printLine(M5EPD_Canvas& canvas, char* line_buffer, int x, int y, const char* fmt, ...)
{
va_list arg;
va_start(arg, fmt);
std::vsprintf(line_buffer, fmt, arg);
canvas.fillCanvas(0);
canvas.drawString(line_buffer, 0, 0);
canvas.pushCanvas(x, y, m5epd_update_mode_t::UPDATE_MODE_DU);
va_end(arg);
}
void setup()
{
pinMode(M5EPD_MAIN_PWR_PIN, OUTPUT);
M5.enableMainPower();
pinMode(M5EPD_EXT_PWR_EN_PIN, OUTPUT);
pinMode(M5EPD_EPD_PWR_EN_PIN, OUTPUT);
pinMode(M5EPD_KEY_RIGHT_PIN, INPUT);
pinMode(M5EPD_KEY_PUSH_PIN, INPUT);
pinMode(M5EPD_KEY_LEFT_PIN, INPUT);
delay(100);
M5.enableEXTPower();
M5.enableEPDPower();
delay(1000);
// M5.begin();
// M5.EPD.Clear(true);
// M5.EPD.SetRotation(IT8951_ROTATE_90);
// M5EPD_Canvas canvas(&M5.EPD);
// canvas.createCanvas(540, 50);
// //canvas.setFreeFont(FF18);
// //canvas.setTextSize(1);
// canvas.setTextSize(1);
// canvas.setTextDatum(TL_DATUM);
// canvas.setTextColor(15);
// canvas.drawString("Hoge Fuga Piyo", 0, 0);
// canvas.pushCanvas(0, 0, m5epd_update_mode_t::UPDATE_MODE_DU);
SPI.begin(14, 13, 12, 4);
SD.begin( TFCARD_CS_PIN, SPI, 40000000);
Serial.begin(115200);
const int loop = 20;
const int height = 20;
int y = height;
char buffer[80];
for(auto bench : benches) {
// y += height; printLine(canvas, buffer, 0, y, "FS: %s", bench->name());
Serial.printf("FS: %s\r\n", bench->name());
bench->init();
auto create_time = bench->getCreateTime(bench->getFS(), bench->tmpFile, loop);
auto open_close_time = bench->getOpenCloseTime(bench->getFS(), bench->tmpFile, loop);
auto remove_time = bench->getRemoveTime(bench->getFS(), bench->tmpFile, loop);
std::array<ReadWriteResult, 5> read_write_times;
for ( int i = 0; i < read_write_times.max_size(); ++i ) {
auto& read_write_time = read_write_times[i];
read_write_time.write_time = bench->getWriteTime(bench->getFS(), bench->tmpFile, (4 << i) * 1024, 8 - i);
read_write_time.read_time = bench->getReadTime(bench->getFS(), bench->tmpFile, (4 << i) * 1024, 8 - i);
read_write_time.size_in_kib = 4 << i;
}
// y += height; printLine(canvas, buffer, 0, y, "Create : %llu [us] %llu [counts/s]", create_time, 1000000ul / create_time);
// y += height; printLine(canvas, buffer, 0, y, "OpenClose: %llu [us] %llu [counts/s]", open_close_time, 1000000ul / open_close_time);
// y += height; printLine(canvas, buffer, 0, y, "Remove : %llu [us] %llu [counts/s]", remove_time, 1000000ul / remove_time);
// for(const auto& read_write_time : read_write_times) {
// y += height; printLine(canvas, buffer, 0, y, "Read %llu[KiB]: %llu [us] %llu [KiB/s]", read_write_time.size_in_kib, read_write_time.read_time, 1000000ul * read_write_time.size_in_kib / read_write_time.read_time);
// y += height; printLine(canvas, buffer, 0, y, "Write %llu[KiB]: %llu [us] %llu [KiB/s]", read_write_time.size_in_kib, read_write_time.write_time, 1000000ul * read_write_time.size_in_kib / read_write_time.write_time);
// }
Serial.printf("Create : %llu [us] %llu [counts/s]\r\n", create_time, 1000000ull / create_time);
Serial.printf("OpenClose: %llu [us] %llu [counts/s]\r\n", open_close_time, 1000000ull / open_close_time);
Serial.printf("Remove : %llu [us] %llu [counts/s]\r\n", remove_time, 1000000ull / remove_time);
for(const auto& read_write_time : read_write_times) {
Serial.printf("Read %llu[KiB]: %llu [us] %llu [KiB/s]\r\n", read_write_time.size_in_kib, read_write_time.read_time, 1000000ull * read_write_time.size_in_kib / read_write_time.read_time);
Serial.printf("Write %llu[KiB]: %llu [us] %llu [KiB/s]\r\n", read_write_time.size_in_kib, read_write_time.write_time, 1000000ull * read_write_time.size_in_kib / read_write_time.write_time);
}
}
}
void loop()
{
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment