Skip to content

Commit

Permalink
Deduplicate static strings
Browse files Browse the repository at this point in the history
  • Loading branch information
bblanchon committed Feb 26, 2025
1 parent af91efd commit d5be7e9
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 3 deletions.
18 changes: 18 additions & 0 deletions extras/tests/JsonDocument/MemberProxy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,24 @@ TEST_CASE("Deduplicate keys") {
Allocate(sizeofString("example")),
});
}

SECTION("string literals") {
doc[0]["example"] = 1;
doc[1]["example"] = 2;
doc.shrinkToFit();

const char* key1 = doc[0].as<JsonObject>().begin()->key().c_str();
const char* key2 = doc[1].as<JsonObject>().begin()->key().c_str();
CHECK(key1 == key2);

REQUIRE(spy.log() ==
AllocatorLog{
Allocate(sizeofPool()),
Allocate(sizeofStaticStringPool()),
Reallocate(sizeofPool(), sizeofPool(6)),
Reallocate(sizeofStaticStringPool(), sizeofStaticStringPool(1)),
});
}
}

TEST_CASE("MemberProxy under memory constraints") {
Expand Down
19 changes: 19 additions & 0 deletions extras/tests/ResourceManager/saveString.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,25 @@ static StringNode* saveString(ResourceManager& resources, const char* s,
return resources.saveString(adaptString(s, n));
}

TEST_CASE("ResourceManager::saveStaticString()") {
SpyingAllocator spy;
ResourceManager resources(&spy);

auto a = resources.saveStaticString("hello");
auto b = resources.saveStaticString("world");
REQUIRE(a != b);

auto c = resources.saveStaticString("hello");
REQUIRE(a == c);

resources.shrinkToFit();
REQUIRE(spy.log() ==
AllocatorLog{
Allocate(sizeofStaticStringPool()),
Reallocate(sizeofStaticStringPool(), sizeofStaticStringPool(2)),
});
}

TEST_CASE("ResourceManager::saveString()") {
ResourceManager resources;

Expand Down
8 changes: 8 additions & 0 deletions src/ArduinoJson/Memory/MemoryPool.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,14 @@ class MemoryPool {
return slots_ + id;
}

SlotId find(const T& value) const {
for (SlotId i = 0; i < usage_; i++) {
if (slots_[i] == value)
return i;
}
return NULL_SLOT;
}

void clear() {
usage_ = 0;
}
Expand Down
9 changes: 9 additions & 0 deletions src/ArduinoJson/Memory/MemoryPoolList.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ class MemoryPoolList {
return pools_[poolIndex].getSlot(indexInPool);
}

SlotId find(const T& value) const {
for (PoolCount i = 0; i < count_; i++) {
SlotId id = pools_[i].find(value);
if (id != NULL_SLOT)
return SlotId(i * ARDUINOJSON_POOL_CAPACITY + id);
}
return NULL_SLOT;
}

void clear(Allocator* allocator) {
for (PoolCount i = 0; i < count_; i++)
pools_[i].destroy(allocator);
Expand Down
10 changes: 7 additions & 3 deletions src/ArduinoJson/Memory/ResourceManager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,10 +114,14 @@ class ResourceManager {
}

SlotId saveStaticString(const char* s) {
auto existingSlotId = staticStringsPools_.find(s);
if (existingSlotId != NULL_SLOT)
return existingSlotId;

auto slot = staticStringsPools_.allocSlot(allocator_);
if (!slot)
return NULL_SLOT;
*slot = s;
if (slot)
*slot = s;

return slot.id();
}

Expand Down

0 comments on commit d5be7e9

Please sign in to comment.