Merge branch 'perf-lut-cache' of https://github.com/jpirnay/crosspoint-reader into mybuild
This commit is contained in:
+60
-19
@@ -87,9 +87,8 @@ bool Section::loadSectionFile(const int fontId, const float lineCompression, con
|
|||||||
uint8_t version;
|
uint8_t version;
|
||||||
serialization::readPod(file, version);
|
serialization::readPod(file, version);
|
||||||
if (version != SECTION_FILE_VERSION) {
|
if (version != SECTION_FILE_VERSION) {
|
||||||
file.close();
|
|
||||||
LOG_ERR("SCT", "Deserialization failed: Unknown version %u", version);
|
LOG_ERR("SCT", "Deserialization failed: Unknown version %u", version);
|
||||||
clearCache();
|
clearCache(); // closes file before removal
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,21 +115,50 @@ bool Section::loadSectionFile(const int fontId, const float lineCompression, con
|
|||||||
viewportWidth != fileViewportWidth || viewportHeight != fileViewportHeight ||
|
viewportWidth != fileViewportWidth || viewportHeight != fileViewportHeight ||
|
||||||
hyphenationEnabled != fileHyphenationEnabled || embeddedStyle != fileEmbeddedStyle ||
|
hyphenationEnabled != fileHyphenationEnabled || embeddedStyle != fileEmbeddedStyle ||
|
||||||
imageRendering != fileImageRendering) {
|
imageRendering != fileImageRendering) {
|
||||||
file.close();
|
|
||||||
LOG_ERR("SCT", "Deserialization failed: Parameters do not match");
|
LOG_ERR("SCT", "Deserialization failed: Parameters do not match");
|
||||||
clearCache();
|
clearCache(); // closes file before removal
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
serialization::readPod(file, pageCount);
|
serialization::readPod(file, pageCount);
|
||||||
file.close();
|
|
||||||
LOG_DBG("SCT", "Deserialization succeeded: %d pages", pageCount);
|
// Sanity check: same upper bound used by TextBlock::deserialize for word count
|
||||||
|
if (pageCount > 10000) {
|
||||||
|
LOG_ERR("SCT", "Deserialization failed: page count %u exceeds maximum", pageCount);
|
||||||
|
clearCache();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load LUT into memory (file is now positioned at the lutOffset field)
|
||||||
|
uint32_t lutOffset;
|
||||||
|
serialization::readPod(file, lutOffset);
|
||||||
|
lut.resize(pageCount);
|
||||||
|
if (!file.seek(lutOffset)) {
|
||||||
|
LOG_ERR("SCT", "Deserialization failed: seek to LUT offset %u failed", lutOffset);
|
||||||
|
clearCache();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (uint32_t& pos : lut) {
|
||||||
|
serialization::readPod(file, pos);
|
||||||
|
if (pos < HEADER_SIZE || pos >= lutOffset) {
|
||||||
|
LOG_ERR("SCT", "Deserialization failed: LUT entry %u out of range [%u, %u)", pos, HEADER_SIZE, lutOffset);
|
||||||
|
clearCache();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// File is intentionally left open; subsequent loadPageFromSectionFile() calls
|
||||||
|
// seek within this handle instead of re-opening the file each time.
|
||||||
|
LOG_DBG("SCT", "Deserialization succeeded: %d pages, LUT cached", pageCount);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Your updated class method (assuming you are using the 'SD' object, which is a wrapper for a specific filesystem)
|
bool Section::clearCache() {
|
||||||
bool Section::clearCache() const {
|
file.close(); // Must be closed before removal on FAT32
|
||||||
|
lut.clear();
|
||||||
|
pageCount = 0;
|
||||||
|
currentPage = 0;
|
||||||
|
|
||||||
if (!Storage.exists(filePath.c_str())) {
|
if (!Storage.exists(filePath.c_str())) {
|
||||||
LOG_DBG("SCT", "Cache does not exist, no action needed");
|
LOG_DBG("SCT", "Cache does not exist, no action needed");
|
||||||
return true;
|
return true;
|
||||||
@@ -280,25 +308,38 @@ bool Section::createSectionFile(const int fontId, const float lineCompression, c
|
|||||||
if (cssParser) {
|
if (cssParser) {
|
||||||
cssParser->clear();
|
cssParser->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cache the LUT in memory and open the file for reading so that
|
||||||
|
// subsequent loadPageFromSectionFile() calls can seek directly without re-opening.
|
||||||
|
if (!Storage.openFileForRead("SCT", filePath, file)) {
|
||||||
|
LOG_ERR("SCT", "Failed to open section file for reading after creation");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this->lut = std::move(lut);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Page> Section::loadPageFromSectionFile() {
|
std::unique_ptr<Page> Section::loadPageFromSectionFile() {
|
||||||
if (!Storage.openFileForRead("SCT", filePath, file)) {
|
if (currentPage < 0 || currentPage >= static_cast<int>(lut.size())) {
|
||||||
|
LOG_ERR("SCT", "loadPageFromSectionFile: page %d out of LUT range (%u entries)", currentPage,
|
||||||
|
static_cast<uint32_t>(lut.size()));
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
file.seek(HEADER_SIZE - sizeof(uint32_t) * 3);
|
if (!file) {
|
||||||
uint32_t lutOffset;
|
// Safety fallback: file was closed unexpectedly; reopen
|
||||||
serialization::readPod(file, lutOffset);
|
LOG_ERR("SCT", "loadPageFromSectionFile: file not open, reopening");
|
||||||
file.seek(lutOffset + sizeof(uint32_t) * currentPage);
|
if (!Storage.openFileForRead("SCT", filePath, file)) {
|
||||||
uint32_t pagePos;
|
return nullptr;
|
||||||
serialization::readPod(file, pagePos);
|
}
|
||||||
file.seek(pagePos);
|
}
|
||||||
|
|
||||||
auto page = Page::deserialize(file);
|
if (!file.seek(lut[currentPage])) {
|
||||||
file.close();
|
LOG_ERR("SCT", "loadPageFromSectionFile: seek to page %d offset %u failed", currentPage, lut[currentPage]);
|
||||||
return page;
|
return nullptr;
|
||||||
|
}
|
||||||
|
return Page::deserialize(file);
|
||||||
|
// File is intentionally NOT closed; stays open for the next page load
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<uint16_t> Section::getPageForAnchor(const std::string& anchor) const {
|
std::optional<uint16_t> Section::getPageForAnchor(const std::string& anchor) const {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "Epub.h"
|
#include "Epub.h"
|
||||||
|
|
||||||
@@ -15,6 +16,7 @@ class Section {
|
|||||||
GfxRenderer& renderer;
|
GfxRenderer& renderer;
|
||||||
std::string filePath;
|
std::string filePath;
|
||||||
FsFile file;
|
FsFile file;
|
||||||
|
std::vector<uint32_t> lut; // Cached page byte-offsets; loaded once, avoids per-page LUT seek
|
||||||
|
|
||||||
void writeSectionFileHeader(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment,
|
void writeSectionFileHeader(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment,
|
||||||
uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled,
|
uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled,
|
||||||
@@ -34,7 +36,7 @@ class Section {
|
|||||||
bool loadSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment,
|
bool loadSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment,
|
||||||
uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, bool embeddedStyle,
|
uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, bool embeddedStyle,
|
||||||
uint8_t imageRendering);
|
uint8_t imageRendering);
|
||||||
bool clearCache() const;
|
bool clearCache();
|
||||||
bool createSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment,
|
bool createSectionFile(int fontId, float lineCompression, bool extraParagraphSpacing, uint8_t paragraphAlignment,
|
||||||
uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, bool embeddedStyle,
|
uint16_t viewportWidth, uint16_t viewportHeight, bool hyphenationEnabled, bool embeddedStyle,
|
||||||
uint8_t imageRendering, const std::function<void(int)>& progressFn = nullptr);
|
uint8_t imageRendering, const std::function<void(int)>& progressFn = nullptr);
|
||||||
|
|||||||
Reference in New Issue
Block a user