From 424594488fee0bd7d7740b74c2775241c7c60b7a Mon Sep 17 00:00:00 2001 From: Jonas Diemer Date: Thu, 18 Dec 2025 12:49:14 +0100 Subject: [PATCH] Caching of spine item sizes for faster book loading (saves 1-4 seconds). (#54) As discussed in https://github.com/daveallie/crosspoint-reader/pull/38#issuecomment-3665142427, #38 --- lib/Epub/Epub.cpp | 55 ++++++++++++++++++++++++++++++++++++----------- lib/Epub/Epub.h | 1 + src/main.cpp | 2 +- 3 files changed, 45 insertions(+), 13 deletions(-) diff --git a/lib/Epub/Epub.cpp b/lib/Epub/Epub.cpp index d1855cc..1477d72 100644 --- a/lib/Epub/Epub.cpp +++ b/lib/Epub/Epub.cpp @@ -148,23 +148,54 @@ bool Epub::load() { return false; } - // determine size of spine items - size_t spineItemsCount = getSpineItemsCount(); - size_t spineItemsSize = 0; - for (size_t i = 0; i < spineItemsCount; i++) { - std::string spineItem = getSpineItem(i); - size_t s = 0; - getItemSize(spineItem, &s); - spineItemsSize += s; - cumulativeSpineItemSize.emplace_back(spineItemsSize); - } - Serial.printf("[%lu] [EBP] Book size: %u\n", millis(), spineItemsSize); - + initializeSpineItemSizes(); Serial.printf("[%lu] [EBP] Loaded ePub: %s\n", millis(), filepath.c_str()); return true; } +void Epub::initializeSpineItemSizes() { + setupCacheDir(); + + size_t spineItemsCount = getSpineItemsCount(); + size_t cumSpineItemSize = 0; + if (SD.exists((getCachePath() + "/spine_size.bin").c_str())) { + File f = SD.open((getCachePath() + "/spine_size.bin").c_str()); + uint8_t data[4]; + for (size_t i = 0; i < spineItemsCount; i++) { + f.read(data, 4); + cumSpineItemSize = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); + cumulativeSpineItemSize.emplace_back(cumSpineItemSize); + // Serial.printf("[%lu] [EBP] Loading item %d size %u to %u %u\n", millis(), + // i, cumSpineItemSize, data[1], data[0]); + } + f.close(); + } else { + File f = SD.open((getCachePath() + "/spine_size.bin").c_str(), FILE_WRITE); + uint8_t data[4]; + // determine size of spine items + for (size_t i = 0; i < spineItemsCount; i++) { + std::string spineItem = getSpineItem(i); + size_t s = 0; + getItemSize(spineItem, &s); + cumSpineItemSize += s; + cumulativeSpineItemSize.emplace_back(cumSpineItemSize); + + // and persist to cache + data[0] = cumSpineItemSize & 0xFF; + data[1] = (cumSpineItemSize >> 8) & 0xFF; + data[2] = (cumSpineItemSize >> 16) & 0xFF; + data[3] = (cumSpineItemSize >> 24) & 0xFF; + // Serial.printf("[%lu] [EBP] Persisting item %d size %u to %u %u\n", millis(), + // i, cumSpineItemSize, data[1], data[0]); + f.write(data, 4); + } + + f.close(); + } + Serial.printf("[%lu] [EBP] Book size: %lu\n", millis(), cumSpineItemSize); +} + bool Epub::clearCache() const { if (!SD.exists(cachePath.c_str())) { Serial.printf("[%lu] [EPB] Cache does not exist, no action needed\n", millis()); diff --git a/lib/Epub/Epub.h b/lib/Epub/Epub.h index 1f2dfa9..f22b630 100644 --- a/lib/Epub/Epub.h +++ b/lib/Epub/Epub.h @@ -32,6 +32,7 @@ class Epub { bool findContentOpfFile(std::string* contentOpfFile) const; bool parseContentOpf(const std::string& contentOpfFilePath); bool parseTocNcxFile(); + void initializeSpineItemSizes(); public: explicit Epub(std::string filepath, const std::string& cacheDir) : filepath(std::move(filepath)) { diff --git a/src/main.cpp b/src/main.cpp index 39c5bd0..d12c701 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -216,7 +216,7 @@ void loop() { return; } - if (inputManager.wasReleased(InputManager::BTN_POWER) && inputManager.getHeldTime() > POWER_BUTTON_WAKEUP_MS) { + if (inputManager.wasReleased(InputManager::BTN_POWER) && inputManager.getHeldTime() > POWER_BUTTON_SLEEP_MS) { enterDeepSleep(); // This should never be hit as `enterDeepSleep` calls esp_deep_sleep_start return;