▲ 7 r/iOSProgramming+1 crossposts

Measured three on-device TTS runtimes against the iOS jetsam budget. All three blew past it. Looking for anyone who's shipped generative audio on-device.

Spent about three weeks trying to run a voice-cloning model on iPhone and closed the project last week. Posting the numbers because I couldn't find anyone else's, and I have two questions at the end. This was for a voice journaling app I work on.

The budget. Foreground app on a 6 GB iPhone gets roughly 250 MB before jetsam takes an interest. The number that matters is phys_footprint from task_vm_info, not resident size and not what the Xcode gauge shows.

The candidate. Kyutai Pocket TTS, 109.5M params, autoregressive. Autoregressive matters because accent lives in phone realisation and phonemic choice, which are sequential. Non-autoregressive models transfer timbre only, so you get your own voice colour over someone else's cadence. Tried that first, it sounded wrong in a way I couldn't articulate until I understood why.

Three ways to run it, all measured, all over budget:

FluidAudio (Core ML, int8) - 270.8 MB after model load, 957.0 MB peak

sherpa-onnx (ONNX Runtime, int8) - 377.0 MB after model load, 685.4 MB peak

chatterbox-turbo (earlier attempt) - 953.7 MB peak

FluidAudio is over budget after loading, before doing any work.

Binary cost too. Linked a minimal executable against libsherpa-onnx.a plus ONNX Runtime with -dead_strip, then stripped it: 22.3 MB. That roughly doubles my app, for a feature most users would never turn on, plus 125 MB of models on disk for the ones who do.

The part I got wrong. My earlier ear tests compared one synthetic clip against another synthetic clip. That ranks them. It cannot tell you whether either is good enough. So I ran a forced-choice test instead: eight pairs, same sentence in each, one a real recording of me and one the clone, sample rate and RMS loudness matched, clip lengths varied so duration gave nothing away, and held-out audio located by cross-correlating the reference against the source recording. I picked my own recording 8 out of 8. p = 0.0039.

Three weeks of runtime work sitting on top of an approval nobody had tested properly. The test took an hour.

Two questions.

Has anyone actually shipped a generative audio model on-device inside the jetsam budget? Everything I found either exceeds it or quietly ships a 3 GB app. I'm also unsure whether Core ML's mmap'd weights get billed to phys_footprint the way malloc'd ONNX buffers do. My numbers came off a Mac, which has no jetsam pressure, so I never got a real device measurement before the ear result closed it.

Second, unrelated thread. I'm moving to on-device retrieval next, hybrid BM25 via SQLite FTS5 plus sentence embeddings from NLEmbedding. Anyone run that combination on iOS? Specifically whether reciprocal rank fusion is worth it when you still need raw score magnitude for an abstention threshold. RRF throws the magnitude away and abstention is what stops the thing making stuff up.

Happy to share the measurement harness if useful.

reddit.com
u/intrepidkarthi — 9 days ago
▲ 0 r/quant

Open source deterministic LOB venue with exact aggressor-side ground truth. Built for microstructure methodology work, looking for holes in the setup

Most microstructure claims get tested on data where the key variable is inferred: aggressor side from the tick rule or Lee-Ready, hidden liquidity guessed at, no way to rerun the same tape twice. I built the opposite instrument. A full matching engine (Go, MIT) with a deterministic simulator on top: same seed, same market, byte for byte, and every trade carries its true aggressor side. Price-time and pro-rata, icebergs, pegs, stops, STP, call auctions, price bands. The book emits full L3.

The market is noise flow by construction, so there is nothing to predict. That is the point: it is a control arm. What that isolates, two examples.

Pipeline error propagation. The tick rule classifies 94.5% of trades correctly on this tape, and the CVD built from it is off by 169% of true magnitude on average, with occasional sign flips (one seed: inferred -81, true +105). Misclassification is conditionally correlated, so the errors compound instead of cancelling. Trivial to show when you hold ground truth, hard to even estimate when you do not. Relevant to anything built from inferred sides, which in practice means trade-only feeds and most crypto data.

Known results reproduce. Kyle's lambda comes out around 0.15 ticks per lot and falls 7.5x when resting depth rises 7.6x. Slicing a parent order beats a block by 7.9% slippage per lot (42 of 50 seeds) while permanent impact is essentially unchanged (23.42 vs 24.47 ticks), so the savings is all temporary impact. Nothing novel, deliberately: an instrument should reproduce the textbook before you point it at anything else.

Limitations, stated plainly: no informed flow unless you write an agent for it, no latency modelling, single venue. It cannot tell you whether a signal works on real markets. It can tell you whether your measurement of a signal survives its own pipeline.

Methodology write-ups, including the wrong turns:

https://github.com/intrepidkarthi/orderbook/blob/main/docs/research/order-flow.md

https://github.com/intrepidkarthi/orderbook/blob/main/docs/research/kyle-lambda.md

https://github.com/intrepidkarthi/orderbook/blob/main/docs/research/ofi.md

Repo: https://github.com/intrepidkarthi/orderbook

If you see a hole in the setup, say so. The project has improved every time someone pushed on it.

reddit.com
u/intrepidkarthi — 17 days ago

I built a stock exchange matching engine in Go that runs in your browser via WebAssembly. Looking for feedback.

A matching engine is the piece at the centre of an exchange. It holds the order book and decides which orders trade against which, and at what price.

The demo is not a mock. It is the real engine compiled to WebAssembly, running in your tab.

https://intrepidkarthi.github.io/orderbook/

Code: https://github.com/intrepidkarthi/orderbook

Money cannot be a float. I knew that going in, but not how far the constraint travels. Prices ended up as int64 ticks and quantities as int64 lots, with decimals converted only at the API boundary, and every layer above had to be rewritten to match.

The hot path cannot allocate either. Book nodes and price levels come from free lists, and the match function appends fills into a buffer the caller owns. Cancel-heavy load runs at p50 83ns, p99 167ns, p999 292ns.

Most of the difficulty was not in matching orders. It was everything around it: what happens when the process dies mid-trade, and what a venue is supposed to do when someone deliberately manipulates the closing price.

MIT licensed. Feedback welcome, especially where I have got it wrong.

reddit.com
u/intrepidkarthi — 24 days ago
▲ 1 r/quant

Comparing against a zero-value decimal.Decimal allocates a big.Int

I have been chasing allocations out of the match path in an order book I am building. Pooling the book nodes and price levels got cancel and level churn to zero. Threading a caller-owned buffer through Match(order, dst []Trade), so fills are appended as values instead of returning a fresh slice of pointers, got the match round trip to zero.

One stubborn group was left, and it was not in the order data. It was the price band check.

The band is a config fraction, a decimal.Decimal, and the common case is that it is disabled and left at its zero value. Comparing against that zero value calls ensureInitialized internally, which allocates a big.Int. So every order was allocating in order to compare a price against a band that was switched off.

The fix was hoisting the comparison to construction: resolve a bandEnabled bool once when the engine is built, and let the per-order path read the bool. Process went from 10 allocs to 4.

Prices and quantities are int64 ticks and lots, so decimal never touched the money path to begin with. It was purely the configuration percentage, evaluated in the wrong place.

Current numbers on an M-series, single core: 6.3ns top-of-book read, 352ns match round trip at 0 allocs/op, and a cancel-heavy flow at p50 83ns, p99 167ns, p999 292ns. Match is the zero-alloc entry point; Process is the ergonomic wrapper that still costs those 4.

github.com/intrepidkarthi/orderbook

u/intrepidkarthi — 24 days ago
▲ 2 r/InvestingandTrading+2 crossposts

Open-source matching engine + microstructure toolkit in Go — order types, L1/L2/L3 data, OFI/Kyle's λ, backtester (MIT)

I've been building **orderbook**, a central-limit-order-book and matching engine

in Go — the piece at the heart of an exchange. It's an embeddable library, and

the whole engine compiles to WebAssembly so you can poke at the real thing in

your browser:

▶ Live demo: https://intrepidkarthi.github.io/orderbook/

▶ Repo: https://github.com/intrepidkarthi/orderbook

What might interest this sub:

- **int64 ticks & lots, no floats** on the money path (an `Instrument` converts

decimals only at the boundary).

- **Zero-allocation hot path** — `Match(order, buf)` appends value-trades into a

caller buffer; submit/cancel/match are **0 allocs/op**. O(1) cancel.

- **Lock-free single-writer core** (LMAX model): one matching goroutine, an MPSC

command queue in front, bounded backpressure that sheds new orders but never

cancels.

- **Deterministic & replayable:** same command stream → byte-identical trades and

book; that's what makes WAL crash-recovery and golden-file tests work.

- **A market-integrity layer grounded in a threat model** — the part I had the

most fun with. I researched real attacks (spoofing convictions, Knight Capital

$440M, the Mango oracle hack, the Bitcoin overflow bug) and built a defense for

each: pre-trade risk controls, surveillance detectors, a self-output guardrail,

an enforcing gateway. Writeup: docs/THREAT-MODEL.md.

Benchmarks (Apple M-series, single core): ~6ns best bid/ask read, ~352ns match

round-trip (0 allocs), cancel-heavy p50/p99/p999 = 83/167/292ns. Race/fuzz/soak

suites in CI.

Honest status: a library + microstructure research harness (OFI, Kyle's λ,

Avellaneda–Stoikov, a sim + backtester), not a live exchange. MIT, v0.6.0.

Feedback and "you did X wrong" very welcome — that's why I'm posting.

reddit.com
u/intrepidkarthi — 27 days ago

I hired ML engineers as a CTO. The interview treadmill looks completely different from the other side of the table

Everyone here is grinding DSA and question lists, so let me tell you what actually decided offers when I was the one deciding.

"Explain overfitting" never rejected anyone. Everyone has the textbook answer. The follow-up did the rejecting: here is a model at 99% on the test set, do you ship it? The candidates who said yes told me they had learned the words but never been burned by a leaky split. The ones who got suspicious of their own good number got the offer.

Same with projects. I would pick one off the resume and ask why not the simpler approach. If the answer was a real tradeoff, we were having an engineer's conversation. If it was "that's what the tutorial used," the project was never theirs, and three more questions always proved it.

The question that auto-rejected the most strong-on-paper candidates: how would you know your model is getting worse in production? Most ML prep stops at the trained model. The job starts after it.

None of this rewards memorisation, which is exactly the point. The lists filter for recall. The follow-ups filter for judgment, because judgment is the thing nobody can teach fast.

What's the follow-up question that broke you in an interview? Genuinely curious what the other side of this looks like now.

reddit.com
u/intrepidkarthi — 2 months ago

I built a free, open-source voice journal that runs 100% on-device — and I honestly can't tell anyone why they'd pick it over just using Notes. Roast my positioning

A few years ago I typed something into a journaling app on the worst night of a fight. Later I read its privacy policy and realized that entry had been sitting on a company's server the whole time. It felt like being read while crying. That's the day DailyVox started.

The bet: a diary should physically not be able to read you. So all the AI transcription, mood analysis, a "Digital Twin" that learns your patterns and runs on-device. No account, no server, works in airplane mode, Apple's privacy label is literally "Data Not Collected." It's free, iPhone-only, and open source (MIT) so you can verify the claim instead of trusting me.

Here's where I'm stuck, and what I want you to tear apart: I can't tell if the problem is the product, the positioning, or how I'm presenting it. "Your journal never leaves your phone" feels obvious to me, but maybe nobody actually cares about privacy enough to switch. Maybe "free with no plan to charge" reads as sketchy, not generous. Maybe the whole premise is solving a problem nobody has.

So roast it — the name, the landing page, the pitch, the free-forever thing. Is verifiable privacy a real reason to switch, or am I in love with a feature nobody wants?

App: getdailyvox.com · Code: github.com/intrepidkarthi/dailyvox

reddit.com
u/intrepidkarthi — 2 months ago