Skip to content

Per-descriptor rate ceilings; make within-transfer Block2 pacing conditional on measured ceiling #10

Description

@QuiteYellow

Follow-up from PR #8 review. Consolidates original follow-up items 2 and 3 into one piece of work, per the review discussion.

Background. PR #8 landed inter-request pacing to avoid RT-OCF request drops, plus the residual-pace() optimization. Two open questions remained:

  • (orig. item 2) Drop within-transfer Block2 pacing entirely?
  • (orig. item 3) Replace the _DEFAULT_RATE_LIMIT_RPS = 5.0 floor with each descriptor's measured ceiling.

The measurement evidence on dropping within-transfer pacing was inconclusive: on a marginal device (dishwasher, 10.0.0.129) an interleaved 40-sweep test showed 2/60 hrefs failing paced vs 5/60 unpaced, but non-significant (Fisher's exact p≈0.44), and the failures were 3 clustered /device/0 congestion events — not 60 independent trials — where the paced sweep also failed in two of the three. So within-transfer pacing could not be shown to help or be shown safe to remove on that device class. Rather than drop it globally on a "should be safe" basis, we fold the decision into the per-descriptor ceiling work.

Plan.

  1. Plumb per-device rate first — this isn't a constant swap. bridge.py:237 constructs DtlsCoapSession(...) without passing rate_limit_rps, so every device currently runs at the _DEFAULT_RATE_LIMIT_RPS = 5.0 default; the measured ceilings live only as comments above the PollTier lists (samples/dryer.py, samples/oven.py), not as a descriptor field. Add a rate field to the descriptor and have the bridge pass it into DtlsCoapSession(rate_limit_rps=...), keeping _DEFAULT_RATE_LIMIT_RPS as the fallback when a descriptor omits it. (Values come from the descriptors — the 3 frozen samples here plus those localthings maintains; the library keeps the 5.0 floor.)
  2. Set each descriptor's ceiling (oven ~8 rps → 125 ms, dryer ~14 rps → 71 ms) so inter-poll spacing in PollScheduler._do_tier is not over-conservative.
  3. Make within-transfer Block2 pacing (if num > 0: self.pace() in DtlsCoapSession.get()) conditional on the measured per-device ceiling rather than unconditional — keep it for devices whose ceiling warrants it, skip it where measured headroom shows continuation GETs are not throttled.
  4. Re-verify multi-block /device/0 on characterized hardware (oven/dryer, fridge/dishwasher) after the change.

Acceptance. Per-descriptor ceilings drive both inter-poll and within-transfer pacing; no regression in Block2 completion on the four characterized appliances; marginal devices (dishwasher) retain their within-transfer insurance.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions