Skip to content

Commit ad5097f

Browse files
committed
core,server: Use new allocator for json type
The new stateless allocator is used for JSON type. The backing memory resource is initialized in engine shard. The function which parses JSON is refactored to no longer accept a memory resource, as the allocator is bound to its thread local memory resource. Signed-off-by: Abhijat Malviya <[email protected]>
1 parent 6b160e9 commit ad5097f

File tree

10 files changed

+33
-26
lines changed

10 files changed

+33
-26
lines changed

src/core/compact_object.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1624,7 +1624,7 @@ MemoryResource* CompactObj::memory_resource() {
16241624

16251625
bool CompactObj::JsonConsT::DefragIfNeeded(PageUsage* page_usage) {
16261626
if (JsonType* old = json_ptr; ShouldDefragment(page_usage)) {
1627-
json_ptr = AllocateMR<JsonType>(DeepCopyJSON(old, memory_resource()));
1627+
json_ptr = AllocateMR<JsonType>(DeepCopyJSON(old));
16281628
DeleteMR<JsonType>(old);
16291629
return true;
16301630
}

src/core/compact_object_test.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -455,14 +455,14 @@ TEST_F(CompactObjectTest, JsonTypeTest) {
455455
"children":[],"spouse":null}
456456
)";
457457
std::optional<JsonType> json_option2 =
458-
JsonFromString(R"({"a":{}, "b":{"a":1}, "c":{"a":1, "b":2}})", CompactObj::memory_resource());
458+
ParseJsonUsingShardHeap(R"({"a":{}, "b":{"a":1}, "c":{"a":1, "b":2}})");
459459

460460
cobj_.SetString(json_str, false);
461461
ASSERT_TRUE(cobj_.ObjType() == OBJ_STRING); // we set this as a string
462462
JsonType* failed_json = cobj_.GetJson();
463463
ASSERT_TRUE(failed_json == nullptr);
464464
ASSERT_TRUE(cobj_.ObjType() == OBJ_STRING);
465-
std::optional<JsonType> json_option = JsonFromString(json_str, CompactObj::memory_resource());
465+
std::optional<JsonType> json_option = ParseJsonUsingShardHeap(json_str);
466466
ASSERT_TRUE(json_option.has_value());
467467
cobj_.SetJson(std::move(json_option.value()));
468468
ASSERT_TRUE(cobj_.ObjType() == OBJ_JSON); // and now this is a JSON type
@@ -477,7 +477,7 @@ TEST_F(CompactObjectTest, JsonTypeTest) {
477477
ASSERT_TRUE(json != nullptr);
478478
ASSERT_TRUE(json->contains("b"));
479479
ASSERT_FALSE(json->contains("firstName"));
480-
std::optional<JsonType> set_array = JsonFromString("", CompactObj::memory_resource());
480+
std::optional<JsonType> set_array = ParseJsonUsingShardHeap("");
481481
// now set it to string again
482482
cobj_.SetString(R"({"a":{}, "b":{"a":1}, "c":{"a":1, "b":2}})", false);
483483
ASSERT_TRUE(cobj_.ObjType() == OBJ_STRING); // we set this as a string
@@ -504,7 +504,7 @@ TEST_F(CompactObjectTest, JsonTypeWithPathTest) {
504504
"title" : "The Night Watch",
505505
"author" : "Phillips, David Atlee"
506506
}]})";
507-
std::optional<JsonType> json_array = JsonFromString(books_json, CompactObj::memory_resource());
507+
std::optional<JsonType> json_array = ParseJsonUsingShardHeap(books_json);
508508
ASSERT_TRUE(json_array.has_value());
509509
cobj_.SetJson(std::move(json_array.value()));
510510
ASSERT_TRUE(cobj_.ObjType() == OBJ_JSON); // and now this is a JSON type

src/core/json/json_object.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,14 +54,14 @@ std::optional<ShortLivedJSON> JsonFromString(std::string_view input) {
5454
return ParseWithDecoder(input, json_decoder<ShortLivedJSON>{});
5555
}
5656

57-
optional<JsonType> JsonFromString(string_view input, PMR_NS::memory_resource* mr) {
58-
return ParseWithDecoder(input, json_decoder<JsonType>{PMR_NS::polymorphic_allocator<char>{mr}});
57+
optional<JsonType> ParseJsonUsingShardHeap(string_view input) {
58+
return ParseWithDecoder(input, json_decoder<JsonType>{detail::StatelessJsonAllocator<char>{}});
5959
}
6060

61-
JsonType DeepCopyJSON(const JsonType* j, PMR_NS::memory_resource* mr) {
61+
JsonType DeepCopyJSON(const JsonType* j) {
6262
std::string serialized;
6363
j->dump(serialized);
64-
auto deserialized = JsonFromString(serialized, mr);
64+
auto deserialized = ParseJsonUsingShardHeap(serialized);
6565
DCHECK(deserialized.has_value());
6666
return std::move(deserialized.value());
6767
}

src/core/json/json_object.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,8 @@ bool operator!=(const StatelessJsonAllocator<T>&, const StatelessJsonAllocator<U
6868
void InitTLJsonHeap(PMR_NS::memory_resource* mr);
6969

7070
using ShortLivedJSON = jsoncons::json;
71-
using JsonType = jsoncons::pmr::json;
71+
using JsonType =
72+
jsoncons::basic_json<char, jsoncons::sorted_policy, detail::StatelessJsonAllocator<char>>;
7273

7374
// A helper type to use in template functions which are expected to work with both ShortLivedJSON
7475
// and JsonType
@@ -82,12 +83,12 @@ std::optional<ShortLivedJSON> JsonFromString(std::string_view input);
8283

8384
// Parses string into JSON, using mimalloc heap for allocations. This method should only be used on
8485
// shards where mimalloc heap is initialized.
85-
std::optional<JsonType> JsonFromString(std::string_view input, PMR_NS::memory_resource* mr);
86+
std::optional<JsonType> ParseJsonUsingShardHeap(std::string_view input);
8687

8788
// Deep copy a JSON object, by first serializing it to a string and then deserializing the string.
8889
// The operation is intended to help during defragmentation, by copying into a page reserved for
8990
// malloc.
90-
JsonType DeepCopyJSON(const JsonType* j, PMR_NS::memory_resource* mr);
91+
JsonType DeepCopyJSON(const JsonType* j);
9192

9293
inline auto MakeJsonPathExpr(std::string_view path, std::error_code& ec)
9394
-> jsoncons::jsonpath::jsonpath_expression<JsonType> {

src/core/json/jsonpath_test.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class TestDriver : public Driver {
3939
template <typename JSON> JSON ValidJson(string_view str);
4040

4141
template <> JsonType ValidJson<JsonType>(string_view str) {
42-
auto res = ::dfly::JsonFromString(str, pmr::get_default_resource());
42+
auto res = ParseJsonUsingShardHeap(str);
4343
CHECK(res) << "Failed to parse json: " << str;
4444
return *res;
4545
}

src/core/page_usage_stats_test.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ TEST_F(PageUsageStatsTest, JSONCons) {
191191
// encoding.
192192
std::string_view data{R"#({"data": "some", "count": 1, "checked": false})#"};
193193

194-
auto parsed = JsonFromString(data, &m_);
194+
auto parsed = ParseJsonUsingShardHeap(data);
195195
EXPECT_TRUE(parsed.has_value());
196196

197197
c_obj_.SetJson(std::move(parsed.value()));

src/server/engine_shard.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,7 @@ void EngineShard::InitThreadLocal(ProactorBase* pb) {
422422

423423
CompactObj::InitThreadLocal(shard_->memory_resource());
424424
SmallString::InitThreadLocal(data_heap);
425+
InitTLJsonHeap(shard_->memory_resource());
425426

426427
shard_->shard_search_indices_ = std::make_unique<ShardDocIndices>();
427428
}

src/server/json_family.cc

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ std::optional<std::string> ConvertJsonPathToJsonPointer(string_view json_path) {
475475
result before invoking SetJsonSize. Note that even after calling std::move on an optional, it may
476476
still hold the JSON value, which can lead to incorrect memory tracking. */
477477
std::optional<JsonType> ShardJsonFromString(std::string_view input) {
478-
return JsonFromString(input, CompactObj::memory_resource());
478+
return ParseJsonUsingShardHeap(input);
479479
}
480480

481481
OpStatus SetFullJson(const OpArgs& op_args, string_view key, string_view json_str) {
@@ -556,8 +556,7 @@ OpResult<bool> SetPartialJson(const OpArgs& op_args, string_view key,
556556
path_exists = true;
557557
if (!is_nx_condition) {
558558
value_was_set = true;
559-
*val = JsonType(parsed_json.value(),
560-
std::pmr::polymorphic_allocator<char>{CompactObj::memory_resource()});
559+
*val = JsonType(parsed_json.value(), detail::StatelessJsonAllocator<char>{});
561560
}
562561
return {};
563562
};
@@ -1526,10 +1525,18 @@ auto OpMemory(const OpArgs& op_args, string_view key, const WrappedJsonPath& jso
15261525
ReadOnlyOperationOptions{false, CallbackResultOptions::DefaultReadOnlyOptions()});
15271526
}
15281527

1529-
// Returns json vector that represents the result of the json query.
1530-
auto OpResp(const OpArgs& op_args, string_view key, const WrappedJsonPath& json_path) {
1531-
auto cb = [](const string_view&, const JsonType& val) { return val; };
1532-
return JsonReadOnlyOperation<JsonType>(op_args, key, json_path, std::move(cb));
1528+
// Returns json vector that represents the result of the json query. A shard local
1529+
// heap allocated JSON cannot be copied and then destroyed on another shard because we use stateless
1530+
// allocators which forward all requests to thread local memory resource. So the value is first
1531+
// copied to the std allocator-backed type ShortLivedJSON.
1532+
OpResult<JsonCallbackResult<ShortLivedJSON>> OpResp(const OpArgs& op_args, string_view key,
1533+
const WrappedJsonPath& json_path) {
1534+
auto cb = [](const string_view&, const JsonType& val) {
1535+
string s;
1536+
val.dump(s);
1537+
return JsonFromString(s);
1538+
};
1539+
return JsonReadOnlyOperation<ShortLivedJSON>(op_args, key, json_path, std::move(cb));
15331540
}
15341541

15351542
// Returns boolean that represents the result of the operation.

src/server/json_family_memory_test.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,8 @@ TEST_F(JsonFamilyMemoryTest, JsonConsDelTest) {
111111

112112
size_t start = GetMemoryUsage();
113113

114-
auto json = dfly::JsonFromString(start_json, JsonFamilyMemoryTest::GetMemoryResource());
115-
void* ptr =
116-
JsonFamilyMemoryTest::GetMemoryResource()->allocate(sizeof(JsonType), alignof(JsonType));
114+
auto json = ParseJsonUsingShardHeap(start_json);
115+
void* ptr = GetMemoryResource()->allocate(sizeof(JsonType), alignof(JsonType));
117116
JsonType* json_on_heap = new (ptr) JsonType(std::move(json).value());
118117

119118
size_t memory_usage_before_erase = GetMemoryUsage() - start;

src/server/rdb_load.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -984,8 +984,7 @@ void RdbLoaderBase::OpaqueObjLoader::HandleBlob(string_view blob) {
984984
} else if (rdb_type_ == RDB_TYPE_JSON) {
985985
size_t start_size = static_cast<MiMemoryResource*>(CompactObj::memory_resource())->used();
986986
{
987-
auto json = JsonFromString(blob, CompactObj::memory_resource());
988-
if (json) {
987+
if (auto json = ParseJsonUsingShardHeap(blob)) {
989988
pv_->SetJson(std::move(*json));
990989
} else {
991990
LOG(INFO) << "Invalid JSON string during rdb load of JSON object: " << blob;

0 commit comments

Comments
 (0)