Status file¶
fastmm-live publishes its live state in a memory-mapped file that monitors such as fastmm-top read; fastmm-gateway publishes its own in the same layout (kind 1, the gateway block). Code: include/fastmm/core/status_segment.hpp. Usage: Monitor a session, Run behind a gateway.
Location and lifetime¶
- The path is
/dev/shm/fastmm-<engine name>.status, where the name is[engine] name;fastmm-live --status <path>chooses another path and--no-statusturns it off. A gateway's is/dev/shm/fastmm-<engine name>.gw.status, with the same flags. - The writer (
fastmm-live's control thread, the gateway's main thread) creates or truncates the file at startup and rewrites the snapshot every 250 ms. The file stays after exit; the last snapshot showsstoppedand the final numbers. - The engine refreshes the counters and latencies it hands to the control thread every
[engine] latency_publish_ms(default 1 s).
Reading it safely¶
The file holds an 8-byte sequence counter followed by one StatusSnapshot. The writer makes the counter odd, writes the snapshot, then makes it even again. A reader copies the snapshot when the counter is even and unchanged across the copy, and retries otherwise; it never blocks the writer.
magic(0x315441545353464D, "MFSSTAT1" little-endian) andversion(currently 18) sit at the same offsets in every version. A reader of another version refuses the file:fastmm-topreports<file> was written by a different FastMM build (status segment version <n>, this fastmm-top reads version <m>).- The layout is internal (Public API); read it with
fastmm-topfrom the same build.
Snapshot fields¶
| Field | Type | Meaning |
|---|---|---|
magic, version |
u64, u32 | see above |
pid |
u32 | process id of the writer |
session_id |
u64 | the journal's session id |
started_ns, updated_ns |
i64 | wall-clock start and last publish, ns since the epoch |
state |
u8 | 0 starting, 1 running, 2 stopping, 3 stopped |
dry_run |
u8 | 1 in --dry-run |
venue_count |
u8 | entries used in venues |
kill_reason |
u8 | KillReason of the global kill switch, 0 while it is not set (below) |
engine_name, strategy |
char[32] | NUL-terminated |
events, book_updates |
u64 | events consumed, book updates applied |
orders_sent, cancels_sent, replaces_sent |
u64 | order messages sent |
fills |
u64 | executions |
risk_rejects, venue_rejects |
u64 | orders refused by the pre-trade checks, by a venue |
risk_reject_reasons, venue_reject_reasons |
6 x | the most frequent RejectReasons, most frequent first; count 0 marks an unused entry |
kills, kill_flags, venue_kills |
u64, u32, u32 | global kill switch trips, the current flag word, per-venue kill switch trips |
kill_latched |
u8 | 1 while a max_loss trip is latched in [engine] kill_file |
flatten_state |
u8 | operator flatten: 0 off, 1 working, 2 flat, 3 timed out, 4 stopped (Operating a running session) |
flatten_instruments_left |
u32 | instruments in the flatten's scope that still hold a position |
flatten_orders |
u64 | reduce-only orders the flatten has sent |
kind |
u8 | 0 fastmm-live, 1 fastmm-gateway |
realized_pnl_raw, unrealized_pnl_raw, fees_raw |
i64 | settlement currency, or [accounting] reporting_currency when it is set; raw fixed point (divide by 1e8) |
pnl_carry_raw |
i64 | net PnL of earlier sessions that [risk] max_loss is measured against, from [engine] kill_file |
max_loss_raw |
i64 | [risk] max_loss as the engine applies it now (fastmm-ctl limits changes it), 0 when off; a gateway's is gateway.max_loss_raw |
quoting_elapsed_ns, quoting_two_sided_ns |
i64 | time since the first order rested, and how much of it had a live order on both sides; both summed over the instruments |
param_updates, param_last_seq, param_last_ns, param_last_origin, param_last_source |
u64, u64, i64, u8, char[40] | strategy parameter updates the engine has applied, and the last one: its publisher's sequence number, when it was applied (wall clock), its origin (0 the strategy's publisher, 1 the control socket) and its --source (Confirm a parameter change) |
param_control_published, param_control_applied |
u64, u64 | the sequence number of the last update the control socket sent, and of the last of those the engine has applied; equal once nothing is pending |
risk_tokens, risk_token_wait_ns, risk_orders_per_sec, risk_burst |
i64, i64, u32, u32 | the [risk] orders_per_sec bucket every account shares: whole tokens left (-1 with the limit off), how long until the next while it is empty, and its rate and burst as the engine applies them now |
latency |
7 x | engine latency intervals, below |
venues |
8 x venue entry | below |
underlyings |
8 x underlying entry | [risk.underlying], in the order of the configuration's base assets: name (char[16], empty for an unused entry), known (u8: 0 while an inverse contract with a position has no mark), net_raw (i64, base units, signed), max_net_raw (i64, the limit applied now, 0 none) |
balance_count, balances |
u32, 32 x balance entry | the balance table (Balance check); a gateway's is the account's over every strategy: asset (char[12]), venue (u8, index into venues), account (u8: the venue's account-wide margin), known (u8: the venue has reported it), free_raw, locked_raw, total_raw, equity_raw, maintenance_raw (i64, asset units), as_of_ns (i64, venue time of the last report) |
perp_count, perps |
u32, 32 x perp entry | the venues' mark, index and funding per derivative that has reported (Perpetuals); a gateway's is the account's: symbol (char[24]), venue (u8), valued_at_mark (u8: the position is valued at the mark now), mark_stale, funding_stale (u8), mark_raw, index_raw (i64), funding_rate (f64, per interval), funding_interval_ns, next_funding_ns (venue time, 0 continuous), open_interest_raw (contracts), mark_age_ns, funding_age_ns (-1 never) (i64), reports (u64) |
quote_count, quotes |
u32, 256 x quote entry | the quote table, one entry per instrument in the table's order (below) |
metric_count, metrics |
u32, 32 x | the numbers the strategy publishes with ctx.metric, in the order it first named them |
gateway |
gateway block | kind 1 only, zero otherwise (below) |
A fastmm-top session is STALE when state is running and updated_ns is more than 3 s old.
Kill flags¶
| Bit | Value | Meaning |
|---|---|---|
| 0 | 0x1 |
global kill switch: no new orders on any venue |
| 1 + venue id | 0x2 (venue 0), 0x4 (venue 1), ... |
one venue only; venues from id 30 share bit 31 |
Kill reasons¶
kill_reason and each venue's kill_reason hold a KillReason, the first reason the flag was set for; the values are listed in Errors and exit codes. fastmm-top shows it as KILLED (<reason>) next to the state and in each venue's kill column.
Latency intervals¶
Index order of latency, each from the named stamps (Architecture):
| Index | Interval | Stamps |
|---|---|---|
| 0 | decode | T0 (socket read) to T1 (decoded) |
| 1 | book apply | T1 to T2 (book updated on the engine thread) |
| 2 | strategy | T2 to T3 (hook returned) |
| 3 | serialize | T3 to T4 (batch handed to the transport) |
| 4 | send | T4 to T5 (push into the outbound ring; with spin_mode = "adaptive" also the eventfd write that wakes the network thread) |
| 5 | tick to trade | T0 to T5 |
| 6 | wire to book | T0 to T2 |
Quote entry¶
What each side of an instrument asks for, what works there and what is in the way, as the engine published it (core/quote_diag.hpp). Prices and quantities are raw fixed point (divide by 1e8).
| Field | Type | Meaning |
|---|---|---|
symbol |
char[24] | the instrument |
instrument, venue |
u32, u8 | its id and its venue's index |
position_raw, avg_px_raw, realized_raw, unrealized_raw |
i64 | the position, its average price and PnL, settlement currency |
mid_raw |
i64 | the book's mid, 0 without a two-sided book |
sides |
2 x side entry | buy, then sell |
Side entry:
| Field | Type | Meaning |
|---|---|---|
desired_px_raw, desired_qty_raw, desired_levels |
i64, i64, u8 | what the last set_quotes asked for: level 0's price, the quantity over every level, the levels; asked even when the engine ignored it |
working_px_raw, working_qty_raw, working_orders |
i64, i64, u16 | the best working quote price, the leaves of the side's quotes, how many |
account_qty_raw |
8 x i64 | those leaves by pool account (0 the primary) |
block |
u8 | the first obstacle: 0 quoting, 1 not wanted, 2 quoting off, 3 pulled, 4 venue killed, 5 feed lag, 6 backoff, 7 starved, 8 refused, 9 pending (Monitoring) |
reason |
u8 | with block 8, the RejectReason of the refusal |
block_since_ns |
i64 | when block began (wall clock) |
note |
{reason char[24], budget_raw i64, set_ns i64} | the strategy's last ctx.note_quote on the side: its reason, the budget it gave (settlement currency, 0 none) and when |
Venue entry¶
| Field | Type | Meaning |
|---|---|---|
name |
char[24] | [venues.<name>] |
md, user, order |
u8 | channel states: 0 down, 1 connecting, 2 live, 3 stale (market data only: a quiet user or order channel is normal and shows as live) |
killed, kill_reason |
u8, u8 | this venue's kill switch is engaged, and its KillReason |
books_synced, books_total |
u32 | books in sync out of subscribed |
md_messages, resyncs |
u64 | market-data messages, book resynchronisations |
orders_sent, cancels_sent, replaces_sent, order_events |
u64 | order traffic on this venue |
reconnects, rest_errors, rate_limit_cooldowns |
u64 | connection health |
clock_offset_ms |
i64 | venue clock minus local clock, ms |
orders_10s, orders_1m, orders_1d, weight |
{window_ms, used, admits, limit} (i64 each) | the account's order budget as its connector last published it (ctx.order_budget without the orders still on their way to it): each window's count, what the connector admits (its cap, below the venue's limit; 0 when the window is not known) and the venue's limit. These count requests in a time window, not open orders |
budget_known, budget_paused |
u8, u8 | the connector has published a budget; the venue asked for a pause (429, -1003) or REST is stopped (418) |
refused_weight, refused_orders_10s, refused_orders_1m, refused_orders_1d, refused_paused |
u64 | orders and replaces the connector's own limiter refused (VenueRateLimit, never sent), by the limit that refused them |
fill_audits, fill_audit_failures |
u64 | fill audits done, and not done (a side could not be read) (Fill audit) |
fill_audit_missing, fill_audit_phantom, fill_audit_mismatched, fill_audit_duplicates |
u64 | executions the venue has and the engine never booked, the engine booked and the venue does not have, that differ, that the store holds twice; each counted once |
wire_tick_to_trade |
{count, p50_ns, p99_ns, p999_ns, max_ns} | socket read to order write on the network thread (the return of the write that carried the order; one write per drain of the outbound ring) |
wire_tick_to_trade_1m, wire_tick_to_trade_1h |
{count, p50_ns, p99_ns, p999_ns, max_ns} | the same over the last minute (60 to 70 s) and the last hour (60 to 70 min) |
feed |
feed entry | multicast venues only (below); state 0 for the others |
Multicast feed¶
The feed entry of a nasdaq_itch venue (Venue connectors); counters are cumulative for the session.
| Field | Type | Meaning |
|---|---|---|
state |
u8 | 0 none (not a multicast venue), 1 down, 2 snapshot (buffering while a GLIMPSE snapshot is taken), 3 live, 4 lost |
backend, xdp_mode |
u8, u8 | 0 kernel, 1 af_xdp, 2 dpdk; the attach mode: 1 zerocopy, 2 native_copy, 3 generic |
packets, bytes |
u64 | MoldUDP64 packets accepted on every line, datagram payload bytes |
line_packets, line_duplicates |
2 x u64 | per line A, B: packets, copies that arrived after the first copy |
line_skew_mean_ns, line_skew_max_ns |
2 x i64 | per line: delay of a duplicate behind the first copy, ns |
gaps, recovered, unrecovered |
u64 | gaps declared, messages delivered from re-requests, sequences given up |
snapshot_recoveries, recovery_overflows |
u64 | GLIMPSE snapshots after the first, recovery buffer overflows |
reorder_high_water, requests |
u64 | most packets held ahead of a gap, re-request packets sent |
malformed, book_errors |
u64 | datagrams that are not MoldUDP64 packets (and bad frames on af_xdp and dpdk), L3 book inconsistencies |
kernel_to_t0 |
{count, p50_ns, p99_ns, p999_ns, max_ns} | kernel receive timestamp to T0 while live (kernel backend) |
xdp_rx_dropped, xdp_rx_invalid_descs, xdp_rx_ring_full, xdp_fill_ring_empty |
u64 | XDP_STATISTICS summed over the sockets; on dpdk, xdp_rx_dropped is the port's imissed plus rx_nombuf |
xdp_fallback |
u64 | subscribed datagrams passed to the kernel because their RX queue has no socket |
Gateway block¶
A gateway (kind 1) fills the header (pid, times, state, dry_run, engine_name, venue_count, venues), kill_flags (bit 0 while the account is killed), kill_reason, kill_latched (the kill file records the trip, which needs [gateway] max_loss), and realized_pnl_raw, unrealized_pnl_raw, fees_raw, pnl_carry_raw with the account's. The engine counters and latencies stay zero.
| Field | Type | Meaning |
|---|---|---|
attachment_count, position_count |
u32, u32 | entries used below |
kill_active |
u8 | the account's kill switch is tripped |
net_pnl_raw, gross_raw, net_raw |
i64 | the account's net PnL (carried + realized + unrealized − fees), gross and net exposure |
trip_net_raw |
i64 | the net PnL when it tripped |
max_loss_raw, max_gross_raw, max_net_raw, max_open_notional_raw |
i64 | [gateway] limits, 0 off |
venues |
8 x routing entry | per venue: md_discarded, order_discarded, unrouted, gateway_cancels, untracked, stale_replays, account_skipped, account_md_lost (u64), refused (11 x u64), and the account on that venue: realized_raw, unrealized_raw, fees_raw, gross_raw, net_raw |
attachments |
16 x attachment | engine (char[32]), pid, id (u32), epoch (u16), blocks (u8: its engine sleeps when idle), attached_ns (i64), md_dropped (u64: market data its rings dropped), refused (11 x u64), instruments (4 x u64: bit i set when it trades positions[i]) |
positions |
256 x position | one per instrument of the gateway's table: symbol (char[24]), venue (u8, index into venues), shared (u8, [gateway.shared]), owner_epoch (u16, the one attachment that trades it; 0 for none, and always for a shared one), traders (u16, attachments trading it), qty_raw (i64, the account's), unattributed_raw and unexplained_raw (i64, a shared one's: see Shared instruments) |
underlyings |
8 x underlying entry | [gateway.underlying]: the account's net position per base asset over every venue, as the snapshot's underlyings |
refused counts in the order GatewayNotOwner, GatewayAccountKilled, GatewayOpenNotional, GatewayGrossNotional, GatewayNetNotional, GatewayRateLimit, GatewayFxRateUnknown, GatewayUnderlyingNet, GatewayUnderlyingMarkUnknown, GatewaySelfTrade, GatewayBalanceShort (Reject reasons).
fastmm-top --json prints the snapshot as one JSON object, with states, kill reasons and latency intervals by name (Command lines); scripts/bench-e2e.sh reads it.