Protobuf Shared‑Field Guard for Zero‑Copy User Feature Propagation in Recommendation Systems
The article presents a Guard abstraction that temporarily borrows and returns Protobuf field pointers via set_allocated/release, eliminating costly CopyFrom operations in recommendation pipelines, enabling zero‑copy field sharing across central‑control and recall stages, improving CPU usage and latency while handling safety and rollback.
This article introduces a Guard abstraction for sharing Protobuf fields (named Guard ) and applies it to the central‑control / recall stages of a recommendation system, achieving noticeable CPU and latency improvements.
In recommendation pipelines, user‑level fields (experiment parameters, behavior sequences, user portraits, etc.) need to travel through the entire chain. The usual practice is to copy these fields from the incoming RPC request to downstream messages, e.g.:
const GetRecommendReq & oReq; // from rpc
RankReq oRankReq;
oRankReq.mutable_user_portrait()->CopyFrom(oReq.user_portrait());While this zero‑copy transmission reduces RPC overhead for downstream services, the CopyFrom call still incurs a copy cost. The article asks whether this copy can be eliminated.
Protobuf provides set_allocated / release interfaces that transfer ownership of a field pointer, removing the need for a copy or swap. Instead of permanently transferring ownership, the article proposes borrowing the pointer temporarily and returning it after use – a classic Guard pattern.
The Guard offers two methods:
void AttachField(Message* pMessage, int iFieldId, Message* pFieldValue);
Message* DetachField(Message* pMessage, int iFieldId);AttachField sets the field on pMessage using set_allocated and records the operation so that the Guard can roll back (release) when it is destroyed, preventing double deletion. DetachField releases the field from pMessage, returns the pointer, and records the release for later rollback, avoiding memory leaks.
The rollback order follows a FILO (stack) discipline, matching the order of C++ local object destruction.
Three typical usage scenarios are demonstrated:
Main‑call pass‑through / split‑package : Directly attach a heavy field from the upstream request to the downstream request without copying.
// usecase:
const AReq & oAReq;
BReq oBReq;
SharePbFieldGuard guard;
guard.AttachField(&oBReq, BReq::BigFieldId, const_cast<AReq &>(oAReq).mutable_bigfield());Sub‑call split‑package : Release heavy fields before copying the request, then re‑attach the same field to each split request, avoiding repeated copies.
// usecase:
Req & oReq;
std::vector<Req> vecMultiReq(n);
SharePbFieldGuard guard;
auto* pField = guard.DetachField(&oReq, Req::BigFieldId);
for (auto&& oSingleReq : vecMultiReq) {
oSingleReq.CopyFrom(oReq);
oSingleReq.set_field(...);
guard.AttachField(&oSingleReq, Req::BigFieldId, pField);
}Multi‑field sharing : Store a map from field IDs to Message* pointers and attach them to each split request in a loop.
std::vector<uint32_t> vecHeavyField{}; // field IDs
SharePbFieldGuard oGuard;
std::unordered_map<uint32_t, ::google::protobuf::Message*> mapIndex2Message;
for (auto uField : vecHeavyField) {
mapIndex2Message[uField] = oGuard.DetachField(&oReq, uField);
}
for (auto&& oSingleReq : vecReq) {
oSingleReq.CopyFrom(oReq);
for (auto uField : vecHeavyField) {
oGuard.AttachField(&oSingleRecallReq, uField, mapIndex2Message[uField]);
}
}The article also discusses safety concerns (e.g., cyclic ownership leading to double delete) and performance questions such as whether the Guard can be implemented without reflection.
Finally, it raises open issues about supporting repeated fields via reflection and how to detect unsafe cycles.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Tencent Cloud Developer
Official Tencent Cloud community account that brings together developers, shares practical tech insights, and fosters an influential tech exchange community.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
