SimplePIR, and what a preprocessed hint really costs
Throughput looks excellent until you account for the client-side state. Measuring where the hint stops being worth it.
SimplePIR reports numbers that sound too good for single-server PIR: throughput within a small factor of a plain memory scan. The trick is a client-side hint computed once, before any query exists. The question I keep coming back to is who pays for that hint, and when it stops being a good trade.
The construction, compressed
Arrange the database as a square matrix . The server publishes, once:
where is derived from a public seed. A query for cell is an LWE encryption of the indicator vector , and the server replies with . The client subtracts the relevant row of to cancel the LWE mask and reads off row .
The server-side work is one matrix–vector product over 32-bit integers. That is why it is fast: no NTTs, no modular reduction chains, just multiply-accumulate that the memory subsystem can keep fed.
The part that is easy to skip
The hint has entries and the client has to store all of it. With and 32-bit entries:
| Database | rows | Hint size |
|---|---|---|
| 1 GB | ~16 K | ~64 MB |
| 8 GB | ~46 K | ~180 MB |
| 32 GB | ~92 K | ~360 MB |
For a browser client, 64 MB of state per database is already at the edge of reasonable. And the hint is not a one-time cost in the way the paper's framing suggests, because:
- It is per-database. Query three different datasets, hold three hints.
- It goes stale on update. Any write to invalidates the rows of that depend on it. For an append-mostly dataset you can patch incrementally; for a mutable one you are re-downloading.
- It has to be downloaded before the first query, which means the latency of query number one is dominated by a transfer that is orders of magnitude larger than the query itself.
Where the break-even sits
Let be the hint size, the per-query communication, and the number of queries a client makes before the hint goes stale. Amortised communication per query is
With and , the hint stops dominating only once . That is a lot of queries against an unchanging database. It is a good fit for something like a certificate transparency lookup or a blocklist check, where clients are long-lived and the data moves slowly. It is a bad fit for anything resembling a search box.
// The measurement that actually matters, and that throughput plots hide
fn amortised_bytes_per_query(hint_bytes: f64, query_bytes: f64, queries: u32) -> f64 {
hint_bytes / queries as f64 + query_bytes
}What I would want reported
Every PIR paper reports throughput in GB/s of database scanned. Almost none report the number above. If you are evaluating a scheme for deployment, ask for:
- hint size as a function of , with the concrete parameter set, not the asymptotic;
- the update story — full recompute, incremental patch, or none;
- amortised per-query bytes at .
Throughput tells you what the server can do. Those three tell you what the client has to accept.