Astro~/0.3
** Docs / Reference / Performance * PAGE 24 / 27
** Astro * Docs
** /docs/reference/performance

Performance

Measured throughput and allocations for every layer, so you can size a link before building it.

Every frame protocol, both compressors, the Reed-Solomon and BCH coders and the checksums are benchmarked. Run them:

make bench

The numbers below came from that suite. They are here so you can answer "will this keep up with my downlink?" without writing the benchmark yourself.

How to read these

goos: darwin   goarch: arm64   cpu: Apple M2 Pro

One machine, one architecture, single-threaded, warm cache, no I/O. Treat them as relative costs between layers, not as a promise about your hardware. The shape of the answer travels; the absolute figures do not.

MB/s counts the octets that went through the operation. Allocations matter as much as time on a flight-adjacent system, so they are in the table.

Figures are rounded to two significant figures, because they move by 10 to 15 percent between runs on the same machine. A difference of a few percent between two rows here means nothing; a factor of two means something.

The bottleneck is Reed-Solomon

OperationThroughputAllocations
RS(255,223) encode30 MB/s3
RS(255,239) encode56 MB/s3
RS decode, no errors30 MB/s3
RS decode, 1 error7.4 MB/s9
RS decode, 8 errors7.2 MB/s23
RS decode, 16 errors6.5 MB/s40

Two things to plan around.

Decoding costs 4.7× more once it is actually correcting. A clean link decodes at about 30 MB/s and a link near the correction limit at about 6.5 MB/s. Size for the bad case, because the bad case is when you need the data.

The stronger code is half the speed. RS(255,223) corrects 16 symbols at about 30 MB/s; RS(255,239) corrects 8 at about 56 MB/s. That is the trade, in numbers.

The cost here is inherent Galois-field arithmetic rather than anything redundant, so it is unlikely to improve much.

Everything else is far cheaper

OperationThroughputAllocations
CADU wrap8000 MB/s1
CADU wrap, randomized1000 MB/s2
TM frame encode310 MB/s2
TM frame decode300 MB/s2
TC frame encode280 MB/s3
TC frame decode300 MB/s2
AOS frame encode290 MB/s7
AOS frame decode300 MB/s3
USLP frame encode280 MB/s11
USLP frame decode300 MB/s3
CRC-16, 1115-octet frame310 MB/s0
CRC-32, 1115-octet frame310 MB/s0

Frame encoding and decoding sit around 300 MB/s across all four data link protocols, and that number is dominated by the CRC: a table-driven CRC-16 over the same 1115 octets runs at about the same rate. The framing itself is nearly free.

Header decoding alone is 3.6 ns for TM and 3.0 ns for AOS, with no allocations, so demultiplexing a stream by VCID before deciding what to keep costs almost nothing.

Packets

OperationThroughputAllocations
Encode, 256 octets4000 MB/s3
Encode, 4096 octets9000 MB/s3
Encode with CRC, 256 octets290 MB/s3
Decode, 256 octets4000 MB/s3
spp.PacketSizer0.59 ns0

The packet layer is not where your time goes, with one exception: WithErrorControl costs an order of magnitude. Encoding a 256-octet packet runs at thousands of MB/s without a CRC and a few hundred with one. The CRC is the whole cost, and it is the same CRC the frame layer already computes over everything. On a link where frames carry a FECF, a per-packet CRC buys you very little for 12× the packet encoding cost.

Compression

OperationThroughputAllocations
LDC compress, smooth ramp48 MB/s14
LDC compress, noise62 MB/s16
LDC decompress, smooth ramp48 MB/s269
LDC decompress, noise73 MB/s269
RHC compress, one cycle9.7 MB/s13
RHC decompress, one cycle33 MB/s7

LDC runs at roughly 50 to 70 MB/s, comfortably faster than the Reed-Solomon that will follow it, so compression is not the constraint in a downlink chain. Decompression allocates 269 times, which is worth knowing if you are processing an archive rather than a live pass.

RHC is measured per cycle over a small housekeeping vector, so its MB/s figure is dominated by per-cycle overhead rather than throughput. 13 allocations per compressed cycle is the number to watch on a spacecraft that runs it every second.

OperationThroughputAllocations
BCH encode69 MB/s1
BCH decode, clean68 MB/s1
BCH decode, with an error2.3 MB/s1
CLTU wrap70 MB/s2

BCH correction is 29× slower than the clean path, but an uplink is kilobits per second, so this never matters. It is listed for completeness.

What is not measured

No end-to-end pipeline benchmark, no concurrent throughput, and nothing for pkg/sle, pkg/cfdp, pkg/bp, pkg/ltp, pkg/pus or pkg/xtce. Those are caller-pumped state machines and parsers whose cost depends far more on how you drive them than on the library, so a single number would mislead.

Things that will bite you

A 300 MB/s frame layer does not mean a 300 MB/s link. The chain is packet, frame, then Reed-Solomon, and the slowest stage sets the rate. On a downlink with RS(255,223) that is about 30 MB/s clean and about 6.5 MB/s while correcting.

These numbers are single-threaded. A Sender is not safe for concurrent use, and neither are the frame services, because a downlink is one ordered stream. Scaling means one pipeline per physical channel, not one per core.

Allocations are per operation, not per octet. Three allocations to encode a 4096-octet packet is cheap. Three allocations to encode a 16-octet packet, two orders of magnitude slower per octet, is the same three allocations doing much less work. Small packets are dominated by fixed cost.

Do not read MB/s on RHC as throughput. It compresses one fixed-length vector per cycle, so the figure reflects per-cycle overhead on a small input.

Reference