mirror of
https://github.com/nlohmann/json.git
synced 2026-10-10 08:27:13 +00:00
Release the spare capacity of the hash index in shrink_to_fit
shrink_to_fit() now trims the tables of large objects like the node array and the decoded strings, and the list of large objects is released as soon as the tables are built. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
2 files changed
+54
No files matched your search
@@ -951,6 +951,8 @@ class basic_json_document
|
|||||||
std::string arena(shrink_arena ? d.arena : std::string());
|
std::string arena(shrink_arena ? d.arena : std::string());
|
||||||
const bool shrink_tape = d.tape != d.inline_tape && d.tape_size != d.tape_cap;
|
const bool shrink_tape = d.tape != d.inline_tape && d.tape_size != d.tape_cap;
|
||||||
const bool into_header = d.tape_size <= d.inline_cap;
|
const bool into_header = d.tape_size <= d.inline_cap;
|
||||||
|
std::vector<document_data::object_index> indexes(d.indexes.capacity() > d.indexes.size() ? d.indexes : std::vector<document_data::object_index>());
|
||||||
|
std::vector<std::uint32_t> index_slots(d.index_slots.capacity() > d.index_slots.size() ? d.index_slots : std::vector<std::uint32_t>());
|
||||||
node* fresh = (shrink_tape && !into_header) ? static_cast<node*>(::operator new (d.tape_size * sizeof(node))) : d.inline_tape;
|
node* fresh = (shrink_tape && !into_header) ? static_cast<node*>(::operator new (d.tape_size * sizeof(node))) : d.inline_tape;
|
||||||
|
|
||||||
if (shrink_tape)
|
if (shrink_tape)
|
||||||
@@ -965,6 +967,14 @@ class basic_json_document
|
|||||||
d.arena.swap(arena);
|
d.arena.swap(arena);
|
||||||
d.base[1] = d.arena.data();
|
d.base[1] = d.arena.data();
|
||||||
}
|
}
|
||||||
|
if (d.indexes.capacity() > d.indexes.size())
|
||||||
|
{
|
||||||
|
d.indexes.swap(indexes);
|
||||||
|
}
|
||||||
|
if (d.index_slots.capacity() > d.index_slots.size())
|
||||||
|
{
|
||||||
|
d.index_slots.swap(index_slots);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -1019,9 +1029,11 @@ class basic_json_document
|
|||||||
d.base[0] = d.src;
|
d.base[0] = d.src;
|
||||||
d.base[1] = d.arena.data();
|
d.base[1] = d.arena.data();
|
||||||
detail::view::build_object_indexes(d);
|
detail::view::build_object_indexes(d);
|
||||||
|
std::vector<std::uint32_t>().swap(d.large_objects); // (only needed while parsing)
|
||||||
d.discarded = false;
|
d.discarded = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
std::vector<std::uint32_t>().swap(d.large_objects);
|
||||||
if (allow_exceptions)
|
if (allow_exceptions)
|
||||||
{
|
{
|
||||||
detail::view::throw_parse_failure<BasicJsonType>(failure, src, size, comments, trailing_commas);
|
detail::view::throw_parse_failure<BasicJsonType>(failure, src, size, comments, trailing_commas);
|
||||||
|
|||||||
@@ -1381,6 +1381,48 @@ TEST_CASE("json_view large objects")
|
|||||||
CHECK(without_collisions.memory_usage() >= with_collisions.memory_usage() + (slots * sizeof(std::uint32_t)));
|
CHECK(without_collisions.memory_usage() >= with_collisions.memory_usage() + (slots * sizeof(std::uint32_t)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("shrink_to_fit releases the tables' spare capacity")
|
||||||
|
{
|
||||||
|
const auto make_text = [](int objects, int members)
|
||||||
|
{
|
||||||
|
std::string text = "[";
|
||||||
|
for (int object = 0; object < objects; ++object)
|
||||||
|
{
|
||||||
|
text += object != 0 ? ",{" : "{";
|
||||||
|
for (int i = 0; i < members + object; ++i)
|
||||||
|
{
|
||||||
|
text += (i != 0 ? ",\"" : "\"") + std::to_string(i) + "\":" + std::to_string(i);
|
||||||
|
}
|
||||||
|
text += '}';
|
||||||
|
}
|
||||||
|
return text + "]";
|
||||||
|
};
|
||||||
|
const std::string small_text = make_text(5, 150);
|
||||||
|
const std::string big_text = make_text(40, 400);
|
||||||
|
|
||||||
|
// reading a big text, and then a small one, leaves the spare capacity
|
||||||
|
// of the big one: shrink_to_fit() brings the document to the size of
|
||||||
|
// one parsed from the small text alone
|
||||||
|
json_document d = json_document::parse(big_text);
|
||||||
|
const std::size_t big = d.memory_usage();
|
||||||
|
d.read(small_text);
|
||||||
|
CHECK(d.memory_usage() >= big);
|
||||||
|
d.shrink_to_fit();
|
||||||
|
json_document fresh = json_document::parse(small_text);
|
||||||
|
fresh.shrink_to_fit();
|
||||||
|
CHECK(d.memory_usage() == fresh.memory_usage());
|
||||||
|
CHECK(d.memory_usage() < big / 2);
|
||||||
|
CHECK(d.root() == json::parse(small_text));
|
||||||
|
for (int object = 0; object < 5; ++object)
|
||||||
|
{
|
||||||
|
const json_view v = d.root()[static_cast<std::size_t>(object)];
|
||||||
|
for (int i = 0; i < 150 + object; ++i)
|
||||||
|
{
|
||||||
|
CHECK(v[std::to_string(i)].get<int>() == i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SECTION("nested, reused, and in arrays")
|
SECTION("nested, reused, and in arrays")
|
||||||
{
|
{
|
||||||
std::string inner = "{";
|
std::string inner = "{";
|
||||||
|
|||||||
Reference in new issue
Block a user