Просмотр исходного кода

Restore the msg-6 Sense capacities and their stack storage

The decoded packet keeps 128 objects and 1024 values again, and the
framing keeps it on the stack instead of allocating per message.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
stan 4 дней назад
Родитель
Сommit
45f251d6a9

+ 4 - 8
Sunrise/src/middleware/bap/activity_message/sense_update.h

@@ -21,14 +21,10 @@ inline constexpr std::uint8_t kLiteralZeroWidth = 1;
 inline constexpr std::size_t kOuterByteCapacity = 514'048;
 /** The client's per-group scratch bounds one group substream. This capacity is also in bytes. */
 inline constexpr std::size_t kGroupByteCapacity = 102'400;
-/**
- * Object rows retained per packet, shared by diagnostics and mission input. A region transition
- * can report more than 128 objects. This is a storage budget, not a wire limit: overflow is
- * reported and an incomplete object is never delivered.
- */
-inline constexpr std::size_t kDecodedObjectCapacity = 256;
-/** Scalar rows retained per packet, absent optional fields included. */
-inline constexpr std::size_t kDecodedValueCapacity = 4096;
+/** Object rows retained for one diagnostic packet. Parsing continues after this fills. */
+inline constexpr std::size_t kDecodedObjectCapacity = 128;
+/** Scalar rows retained for one diagnostic packet. Parsing continues after this fills. */
+inline constexpr std::size_t kDecodedValueCapacity = 1024;
 /** Runtime SDK row sentinel shared without depending on the State layer. */
 inline constexpr std::uint32_t kAbsentRuntimeRow = (std::numeric_limits<std::uint32_t>::max)();
 

+ 2 - 4
Sunrise/src/server/activity/host_runtime.h

@@ -40,11 +40,9 @@ inline constexpr std::size_t kClientMessageHistoryCapacity = 512;
 /** Decoded packet details retained separately from the high-volume metadata history. */
 inline constexpr std::size_t kClientMessageDetailCapacity = 64;
 /** Latest complete msg-6 object observations retained for one activity generation. */
-inline constexpr std::size_t kSenseObservationCapacity =
-    middleware::bap::activity_message::sense_update::kDecodedObjectCapacity;
+inline constexpr std::size_t kSenseObservationCapacity = 128;
 /** Typed values owned by the retained msg-6 observations for one activity generation. */
-inline constexpr std::size_t kSenseObservationValueCapacity =
-    middleware::bap::activity_message::sense_update::kDecodedValueCapacity;
+inline constexpr std::size_t kSenseObservationValueCapacity = 1024;
 /** Per-slot counts the squad Sense body can carry. Its nested array is eight elements. */
 inline constexpr std::size_t kSquadSlotCapacity = 8;
 /** Objective task groups a squad publishes one cost for. */

+ 22 - 35
Sunrise/src/server/bap/encrypted/activity_message/activity_message_framing.cpp

@@ -2,8 +2,6 @@
 #include <array>
 #include <cstddef>
 #include <cstdint>
-#include <memory>
-#include <new>
 #include <span>
 
 #include "../../../../middleware/bap/activity_message/cinematic_incident.h"
@@ -164,20 +162,9 @@ bool frame_only(const ActivityClientBinding& binding,
         kFramingRoutes.end(),
         [adapter](const FramingRoute& candidate) noexcept { return candidate.adapter == adapter; });
     service::incident::Incident parsedIncident{};
+    sense_update::SenseUpdate parsedSense{};
     const bool isIncident = adapter == IngressAdapter::incidentHostIncident;
     const bool isSense = adapter == IngressAdapter::senseUpdateHostSense;
-    // Packet storage is shared by diagnostics and mission delivery; keep its bounded
-    // arrays off the networking thread's stack, including the submission copy.
-    std::unique_ptr<sense_update::SenseUpdate> parsedSense;
-    std::unique_ptr<server::activity::host::SenseInput> senseInput;
-    if (isSense) {
-        parsedSense.reset(new (std::nothrow) sense_update::SenseUpdate{});
-        senseInput.reset(new (std::nothrow) server::activity::host::SenseInput{});
-        if (!parsedSense || !senseInput) {
-            report_message(request.messageType, request.sessionId, "sense_storage_unavailable");
-            return false;
-        }
-    }
     receipts::Framed framed{};
     if (isSense) {
         const activity_sdk::Snapshot catalog = activity_sdk::snapshot();
@@ -185,8 +172,8 @@ bool frame_only(const ActivityClientBinding& binding,
         const sense_update::Resolver resolver{&context, resolve_sense_group, resolve_sense_slot};
         std::size_t consumedBits = 0;
         static_cast<void>(sense_update::decode_sense_update(
-            request.payload, resolver, *parsedSense, consumedBits));
-        framed = receipts::frame_sense_update(request, *parsedSense);
+            request.payload, resolver, parsedSense, consumedBits));
+        framed = receipts::frame_sense_update(request, parsedSense);
     } else {
         framed = isIncident ? receipts::frame_incident_copy(request, parsedIncident)
                  : row != kFramingRoutes.end() ? row->frame(request)
@@ -195,8 +182,8 @@ bool frame_only(const ActivityClientBinding& binding,
     DiagnosticBody diagnostic{};
     diagnostic.consumedBits = framed.consumedBits;
     diagnostic.status = diagnostic_status(framed, isIncident);
-    diagnostic.sense = isSense ? &parsedSense->decoded : nullptr;
-    if (isSense && parsedSense->decoded.status == sense_update::DecodeStatus::partial) {
+    diagnostic.sense = isSense ? &parsedSense.decoded : nullptr;
+    if (isSense && parsedSense.decoded.status == sense_update::DecodeStatus::partial) {
         diagnostic.status = server::activity::host::ClientMessageStatus::decodedPartial;
     }
     const std::uint64_t clientMessageSequence = record(request,
@@ -205,30 +192,30 @@ bool frame_only(const ActivityClientBinding& binding,
                                                        &binding.session,
                                                        binding.bindingGeneration,
                                                        diagnostic);
-    if (isSense && parsedSense->decoded.status != sense_update::DecodeStatus::malformed) {
-        server::activity::host::SenseInput& input = *senseInput;
+    if (isSense && parsedSense.decoded.status != sense_update::DecodeStatus::malformed) {
+        server::activity::host::SenseInput input{};
         input.binding = binding.session;
         input.sourceGeneration = binding.bindingGeneration;
         input.clientMessageSequence = clientMessageSequence;
-        input.epochFirst = parsedSense->epoch.first;
-        input.epochSecond = parsedSense->epoch.second;
+        input.epochFirst = parsedSense.epoch.first;
+        input.epochSecond = parsedSense.epoch.second;
         input.payloadBytes = static_cast<std::uint32_t>(request.payload.size());
         input.peerHeardMask = request.peerHeardMask;
-        input.tailBits = parsedSense->tailBits;
+        input.tailBits = parsedSense.tailBits;
         input.consumedBits = static_cast<std::uint32_t>(framed.consumedBits);
-        input.firstGroupBits = parsedSense->firstGroupBits;
-        input.firstRegistryKey = parsedSense->firstRegistryKey;
-        input.groupsSeen = parsedSense->decoded.groupsSeen;
-        input.groupsDecoded = parsedSense->decoded.groupsDecoded;
-        input.groupsSkipped = parsedSense->decoded.groupsSkipped;
-        input.objectsSeen = parsedSense->decoded.objectsSeen;
-        input.objectsDecoded = parsedSense->decoded.objectsDecoded;
-        input.firstSlotIndex = parsedSense->firstSlotIndex;
-        input.firstSlotType = parsedSense->firstSlotType;
-        input.decodeStatus = parsedSense->decoded.status;
+        input.firstGroupBits = parsedSense.firstGroupBits;
+        input.firstRegistryKey = parsedSense.firstRegistryKey;
+        input.groupsSeen = parsedSense.decoded.groupsSeen;
+        input.groupsDecoded = parsedSense.decoded.groupsDecoded;
+        input.groupsSkipped = parsedSense.decoded.groupsSkipped;
+        input.objectsSeen = parsedSense.decoded.objectsSeen;
+        input.objectsDecoded = parsedSense.decoded.objectsDecoded;
+        input.firstSlotIndex = parsedSense.firstSlotIndex;
+        input.firstSlotType = parsedSense.firstSlotType;
+        input.decodeStatus = parsedSense.decoded.status;
         input.verdict = framed.verdict;
-        input.decoded = parsedSense->decoded;
-        input.hasFirstObject = parsedSense->hasFirstObject;
+        input.decoded = parsedSense.decoded;
+        input.hasFirstObject = parsedSense.hasFirstObject;
         const auto refusal = server::activity::host::submit_sense(input);
         if (refusal != server::activity::host::IngressRefusal::none) {
             report_message(request.messageType,