Skip to content

Replace the per-slot statistics file with a non-perturbing stage recorder, and bump the libe3 submodule #4

Description

@Thecave3

Goal

Replace the current per-slot statistics file with a recorder that does not
perturb what it measures, and decompose the controller's share of the E3 data
path into stages that join the library's own records.

Two problems with the current mechanism

  1. It writes on the data path. The per-slot stage CSV opens an ofstream,
    writes a row, and flushes it once per slot, inside the sample handler.
    A synchronous formatted write plus a flush on a per-slot path costs orders of
    magnitude more than the intervals it is trying to record, so the numbers it
    produces include a large and variable contribution from the act of recording
    them.

  2. It depends on something that does not exist. The code comments state that
    the downstream send stages "are measured library-side in libe3's
    publisher-stage CSV (--pub-stages-log), joinable by message_id". There is no
    such option in libe3, on any branch. So the send side of the path is
    currently unmeasured, and the CSV that exists stops at the handoff.

Scope

Stage What
Hook to codelet already derived from the RAN-side timestamps
Codelet to dispatcher already derived
Dispatcher to handler the queue wait, already derived
Shared-memory publish currently timed inline
E3SM encode the Service Model payload encoder
Emit / fan-out the handoff into the library, per subscriber
Everything downstream owned by libe3, not by this repository

E3SM and E3AP are separate boxes. This repository owns the Service Model
codec. E3AP framing, queuing, encoding and the connector send are the library's,
and are instrumented there. Do not re-time them here; join to them instead.

Mechanism

Use latrec, the per-thread lock-free ring recorder that libe3 ships in
include/libe3/latrec.h: one clock_gettime(CLOCK_MONOTONIC) plus four stores
per stamp into an mmap-backed ring. No syscall, no allocation, no formatting, no
lock, and no I/O on the data path. Conversion to a table happens offline, out of
process, against the mmap'd rings.

A stage block is reserved for this controller in wineslab/libe3#55. Use those
identifiers; do not invent your own.

The recorder is gated by a single runtime environment variable and is off by
default, so the same binary runs traced and untraced. Once it is in, the
--stats-log option and its per-slot flush should go: keeping two recording
mechanisms means one of them is always the one that is wrong.

Work items

  • Bump the libe3 submodule. It is currently pinned to a commit from the
    JSON-encoder camelCase change, which predates a large amount of the
    library's current behavior, including several data-quality fixes to the
    transport and teardown paths. Measurements taken against that pin are not
    comparable with anything else. Bump it, and rebuild against current main.
  • Replace the per-slot CSV with latrec stamps at the same boundaries.
  • Add a stamp at the E3SM encode boundary, distinct from the emit
    boundary.
  • Remove the --pub-stages-log references from the comments, and instead
    document that the downstream stages come from the library's own records,
    joined by the message identifier the library already assigns.
  • Confirm the join actually works end to end: a controller record and a
    library record for the same indication must be pairable.

Exploration first

Do not assume the code locations beyond what is stated above. Find and record
them back in this issue
as file:function for:

  1. Where the sample handler is entered and where each currently-derived stage
    boundary sits.
  2. Where the Service Model payload is encoded.
  3. Where the indication is handed to the library, per subscriber.
  4. Where the message identifier that keys the join is available.

Data-taking review (mandatory)

This must be a permanent, flag-gated capability, not a throwaway.

  • Confirm no stamp allocates, formats, locks, or writes a file on the sample
    path once the CSV is gone.
  • Quantify what the old mechanism was costing: run the same workload with
    the CSV enabled and with latrec enabled, and report both against a clean
    run. This is worth recording, because it tells us how much of the existing
    per-slot numbers were measurement artifact.
  • Record the ring sizing used and whether any capture wrapped.

Acceptance

  • Merged, with the submodule bumped and the build green against current
    library main.
  • The per-slot flushing CSV is removed.
  • One captured run produces complete, ordered records for the stages above,
    joinable to the library's records by the message identifier.
  • The exploration table (file:function per stage) is filled in above.
  • The old-versus-new overhead comparison is recorded here.

Closing paragraph

When this is done, write a closing paragraph here covering: what landed, the
stage identifiers now emitted and where, what the old per-slot CSV was costing,
how the join to the library's records was verified, and anything still open.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions