Alex B and Claude Opus 5.5
8d2ae405e8
perf(store): cache an observation's parsed time in 8 bytes ( #2196 )
...
Refs #2148 .
## Problem
`StoreObs` is the store's most numerous struct: 400k of them on a week
of a busy regional network. Its lazy timestamp cache (#1481 ) is a
`time.Time`, a `sync.Once` and a `bool`, together 40 bytes. On current
master that makes the struct 200 bytes, which puts every observation in
the 208-byte size class.
## Change
The cache is now a single `atomic.Int64`:
- `0` before the first call;
- the parsed time as UTC nanoseconds after it;
- or one of two sentinels: one for empty or unparseable strings, and one
for times it can't hold exactly (a non-UTC offset, or outside
`UnixNano`'s range). Those are re-parsed on each call so their location
is preserved.
Concurrent first calls may both parse; they store the same value.
`StoreObs` is now 160 bytes, in the 160-byte size class: 48 bytes × 400k
observations ≈ **19 MB** less heap. The first parse costs the same;
cached reads now build the `time.Time` from an int.
## Tests
- `TestStoreObsFitsIn160Bytes`: red commit first.
- `TestStoreObsParsedTimeMatchesParse`: Z, nanosecond, offset, SQL,
empty, garbage and epoch inputs give the same time and location as
`time.Parse`, on the first and the cached call.
- `TestStoreObsParsedTimeConcurrentFill`.
- The existing `storeobs_parsedtime_test.go` still passes.
- `go test ./cmd/server` passes, and `-race` passes on the ParsedTime,
retransmission and observer analytics tests.
## This PR or #2149
#2149 fixes #2148 by reordering these same three fields. The two
conflict, so here is how they compare. Sizes are
`unsafe.Sizeof(StoreObs{})` on each branch, with Go's heap size class
beside them:
| | struct | heap per observation | saved per observation | saved at
400k observations |
|---|---|---|---|---|
| master | 200 B | 208 B | – | – |
| #2149 (field reorder) | 192 B | 192 B | 16 B | ~6.4 MB |
| this PR (one 8-byte field) | 160 B | 160 B | 48 B | ~19 MB |
- **#2149:** a pure field reorder with no change in behaviour. It is the
smallest, safest change and the easiest to review. It saves a third of
what this PR does.
- **This PR:** three times the saving, but more code. It adds two
sentinel values, and re-parses on each call any timestamp with a non-UTC
offset. The store writes UTC (`Z`), so that path is rare. It is tested
against `time.Parse` on edge cases, concurrently, and under `-race`.
Options:
1. **Take this PR.** #2149 then has nothing left to reorder.
2. **Take #2149 now, and this PR after it** as a follow-up for the
further 32 bytes per observation. I'll rebase onto #2149 if it lands
first.
3. **Take only #2149** if the smaller, simpler change is preferred.
No config or UI changes.
🤖 Generated with [Claude Code](https://claude.com/claude-code )
https://claude.ai/code/session_01KaR4xu8gVykQBkH8yG8m6H
---------
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com >
2026-10-13 09:01:57 +02:00
..
2026-10-10 18:20:49 +02:00
2026-10-08 22:16:49 +02:00
2026-10-10 18:20:49 +02:00
2026-10-07 09:25:29 +02:00
2026-10-07 09:25:29 +02:00
2026-10-08 21:38:30 +02:00
2026-10-08 21:38:30 +02:00
2026-10-10 18:20:49 +02:00
2026-10-08 22:02:39 +02:00
2026-10-08 21:38:30 +02:00
2026-10-10 18:20:49 +02:00
2026-10-08 21:38:30 +02:00
2026-10-03 12:16:55 +02:00
2026-10-03 12:16:55 +02:00
2026-10-03 12:16:55 +02:00
2026-10-03 12:16:55 +02:00
2026-10-03 12:16:55 +02:00
2026-10-11 09:51:48 +02:00
2026-09-22 07:55:37 +02:00
2026-05-21 14:00:15 -07:00
2026-10-11 09:51:48 +02:00
2026-09-13 19:59:37 +02:00
2026-09-13 19:59:37 +02:00
2026-09-04 16:02:59 +02:00
2026-10-10 21:22:20 +02:00
2026-10-07 09:25:29 +02:00
2026-10-08 22:02:39 +02:00
2026-10-08 22:02:39 +02:00
2026-10-08 21:38:30 +02:00
2026-10-07 09:25:29 +02:00
2026-10-10 18:20:49 +02:00
2026-10-10 18:08:51 +02:00
2026-10-08 21:38:30 +02:00
2026-10-08 22:02:39 +02:00
2026-10-08 22:02:39 +02:00
2026-10-07 09:25:29 +02:00
2026-10-07 11:20:44 +02:00
2026-10-11 11:28:20 +02:00
2026-10-11 11:28:20 +02:00
2026-10-10 18:20:49 +02:00
2026-10-10 18:20:49 +02:00
2026-10-10 18:20:49 +02:00
2026-10-08 16:26:10 +02:00
2026-09-16 09:02:13 +02:00
2026-05-18 22:51:23 -07:00
2026-05-18 22:51:23 -07:00
2026-05-18 22:51:23 -07:00
2026-06-27 22:03:05 -07:00
2026-06-04 03:21:26 -07:00
2026-09-03 18:52:03 +02:00
2026-10-09 19:58:42 +02:00
2026-10-09 19:58:42 +02:00
2026-06-04 13:14:09 +00:00
2026-09-03 18:52:03 +02:00
2026-10-12 12:41:46 +02:00
2026-10-05 20:32:40 +02:00
2026-09-13 20:36:34 +02:00
2026-09-03 18:52:03 +02:00
2026-05-25 22:16:14 -07:00
2026-06-07 03:43:29 -07:00
2026-09-16 09:02:13 +02:00
2026-09-16 09:02:13 +02:00
2026-09-03 18:52:03 +02:00
2026-10-13 08:37:54 +02:00
2026-06-03 13:58:04 -07:00
2026-06-06 22:45:05 -07:00
2026-10-10 18:20:49 +02:00
2026-09-02 09:50:18 +02:00
2026-09-03 18:52:03 +02:00
2026-09-02 09:50:18 +02:00
2026-05-18 12:27:44 -07:00
2026-09-03 18:52:03 +02:00
2026-09-13 19:59:37 +02:00
2026-05-21 14:00:15 -07:00
2026-10-10 18:20:49 +02:00
2026-10-10 18:20:49 +02:00
2026-10-10 18:20:49 +02:00
2026-10-10 18:20:49 +02:00
2026-05-21 11:39:49 -07:00
2026-05-21 11:39:49 -07:00
2026-05-21 11:39:49 -07:00
2026-09-03 18:52:03 +02:00
2026-10-10 21:20:40 +02:00
2026-10-13 08:44:49 +02:00
2026-10-13 08:44:49 +02:00
2026-10-13 08:44:49 +02:00
2026-10-13 08:44:49 +02:00
2026-06-06 22:45:05 -07:00
2026-10-13 08:44:49 +02:00
2026-10-10 18:20:49 +02:00
2026-05-30 13:22:41 -07:00
2026-05-30 13:22:41 -07:00
2026-10-10 18:20:49 +02:00
2026-06-19 11:37:16 -07:00
2026-06-27 22:03:05 -07:00
2026-06-27 22:03:05 -07:00
2026-10-12 12:41:46 +02:00
2026-06-04 14:41:00 -07:00
2026-09-02 13:10:43 +00:00
2026-09-23 10:05:59 +02:00
2026-10-10 11:03:56 +02:00
2026-10-13 08:35:20 +02:00
2026-06-12 19:10:44 -07:00
2026-05-15 22:34:21 -07:00
2026-09-03 18:52:03 +02:00
2026-09-03 18:52:03 +02:00
2026-10-10 18:20:49 +02:00
2026-10-10 18:20:49 +02:00
2026-09-22 23:55:55 +02:00
2026-10-11 09:51:48 +02:00
2026-09-03 18:52:03 +02:00
2026-06-29 15:53:59 -07:00
2026-09-17 21:58:34 +02:00
2026-09-20 15:12:36 +02:00
2026-10-12 12:41:46 +02:00
2026-06-04 16:27:48 -07:00
2026-05-19 23:53:41 -07:00
2026-09-05 09:57:44 +02:00
2026-10-08 21:51:42 +02:00
2026-10-07 09:25:29 +02:00
2026-06-27 22:03:05 -07:00
2026-09-04 15:15:16 +02:00
2026-09-04 15:15:16 +02:00
2026-09-03 18:52:03 +02:00
2026-06-07 09:28:51 -07:00
2026-06-19 11:37:16 -07:00
2026-09-16 09:02:13 +02:00
2026-06-11 10:10:12 -07:00
2026-06-11 10:10:12 -07:00
2026-10-12 12:42:17 +02:00
2026-05-15 16:21:14 +00:00
2026-05-16 19:55:00 +00:00
2026-09-03 18:52:03 +02:00
2026-05-15 20:24:55 -07:00
2026-05-15 22:46:25 -07:00
2026-09-16 09:02:13 +02:00
2026-09-06 21:00:44 +02:00
2026-10-12 12:41:46 +02:00
2026-10-13 08:37:54 +02:00
2026-09-16 09:02:13 +02:00
2026-05-21 14:00:15 -07:00
2026-10-09 19:58:42 +02:00
2026-05-17 16:13:11 +00:00
2026-05-19 08:08:28 -07:00
2026-05-18 23:19:27 -07:00
2026-09-16 09:02:13 +02:00
2026-06-25 05:05:46 -07:00
2026-09-16 09:02:13 +02:00
2026-06-11 07:38:36 -07:00
2026-09-03 18:52:03 +02:00
2026-06-11 07:38:36 -07:00
2026-06-06 22:44:59 -07:00
2026-09-16 09:02:13 +02:00
2026-09-16 09:02:13 +02:00
2026-10-12 11:13:53 +02:00
2026-09-16 09:02:13 +02:00
2026-09-16 09:02:13 +02:00
2026-10-11 11:28:20 +02:00
2026-10-11 11:28:20 +02:00
2026-10-07 09:25:29 +02:00
2026-09-03 18:52:03 +02:00
2026-09-16 09:02:13 +02:00
2026-09-16 09:02:13 +02:00
2026-09-02 10:27:48 +02:00
2026-06-30 15:16:31 -07:00
2026-06-12 08:11:02 -07:00
2026-09-02 10:27:48 +02:00
2026-10-08 15:58:07 +02:00
2026-09-16 09:02:13 +02:00
2026-05-21 14:00:15 -07:00
2026-09-16 09:02:13 +02:00
2026-09-03 18:52:03 +02:00
2026-09-03 18:52:03 +02:00
2026-09-03 18:52:03 +02:00
2026-05-29 02:42:21 -07:00
2026-05-29 02:42:21 -07:00
2026-05-29 02:42:21 -07:00
2026-05-29 02:42:21 -07:00
2026-05-16 10:14:44 -07:00
2026-10-12 12:41:46 +02:00
2026-09-03 18:52:03 +02:00
2026-09-16 09:02:13 +02:00
2026-09-13 19:59:56 +02:00
2026-09-16 09:02:13 +02:00
2026-05-19 23:53:41 -07:00
2026-10-10 11:03:56 +02:00
2026-10-10 11:03:56 +02:00
2026-09-03 18:52:03 +02:00
2026-09-13 21:09:51 +02:00
2026-09-22 07:55:37 +02:00
2026-09-22 07:55:37 +02:00
2026-09-13 19:59:56 +02:00
2026-09-13 19:59:56 +02:00
2026-09-16 09:02:13 +02:00
2026-06-09 03:23:48 -07:00
2026-10-08 16:26:15 +02:00
2026-09-16 09:02:13 +02:00
2026-10-09 21:20:34 +02:00
2026-10-09 21:20:34 +02:00
2026-06-19 11:37:16 -07:00
2026-06-19 11:37:16 -07:00
2026-09-23 09:45:18 +02:00
2026-05-18 09:22:27 -07:00
2026-09-03 18:52:03 +02:00
2026-10-10 21:21:50 +02:00
2026-10-08 22:02:39 +02:00
2026-10-10 20:54:35 +02:00
2026-10-10 20:54:35 +02:00
2026-10-10 20:54:35 +02:00
2026-10-10 18:20:49 +02:00
2026-10-10 20:54:35 +02:00
2026-10-10 20:54:35 +02:00
2026-10-10 20:54:35 +02:00
2026-10-08 22:02:39 +02:00
2026-10-10 20:54:35 +02:00
2026-10-11 14:31:12 +02:00
2026-10-11 14:31:12 +02:00
2026-10-13 09:01:57 +02:00
2026-09-22 11:08:17 +02:00
2026-09-03 18:52:03 +02:00
2026-09-02 11:07:08 +02:00
2026-09-03 18:52:03 +02:00
2026-09-02 09:50:26 +02:00
2026-05-29 01:08:12 -07:00
2026-05-29 01:08:12 -07:00
2026-10-13 08:37:54 +02:00
2026-05-29 02:42:21 -07:00
2026-05-29 02:42:21 -07:00
2026-09-03 18:52:03 +02:00
2026-09-03 18:52:03 +02:00
2026-10-10 17:39:33 +02:00
2026-07-07 00:12:44 -07:00
2026-09-03 18:52:03 +02:00
2026-10-11 11:28:20 +02:00
2026-09-02 18:34:59 +02:00
2026-05-17 16:13:11 +00:00
2026-05-25 22:32:00 -07:00
2026-06-04 23:48:47 -07:00
2026-10-05 20:32:40 +02:00
2026-05-15 22:46:28 -07:00
2026-05-15 22:46:28 -07:00
2026-05-15 22:46:28 -07:00
2026-05-15 22:46:28 -07:00
2026-05-15 22:46:28 -07:00
2026-09-02 09:50:09 +02:00
2026-09-03 18:52:03 +02:00
2026-10-12 12:45:41 +02:00
2026-10-08 14:34:31 +02:00
2026-10-08 14:34:31 +02:00
2026-10-12 12:41:46 +02:00
2026-09-02 14:34:20 +02:00
2026-10-08 14:34:31 +02:00
2026-10-09 19:58:42 +02:00
2026-10-10 10:58:33 +02:00
2026-09-30 11:39:25 +02:00
2026-10-09 19:58:42 +02:00
2026-09-30 11:39:25 +02:00
2026-09-30 11:39:25 +02:00
2026-09-30 11:39:25 +02:00
2026-09-03 18:52:03 +02:00
2026-09-03 18:52:03 +02:00
2026-05-08 16:29:23 -07:00
2026-05-08 16:29:23 -07:00
2026-06-07 09:28:51 -07:00
2026-09-16 09:02:13 +02:00
2026-06-06 22:45:05 -07:00
2026-05-15 09:16:39 -07:00
2026-09-16 09:02:13 +02:00
2026-10-10 18:20:49 +02:00
2026-10-08 21:51:42 +02:00
2026-10-08 21:51:42 +02:00
2026-10-07 09:25:29 +02:00
2026-06-27 22:03:05 -07:00
2026-06-27 22:03:05 -07:00
2026-10-10 21:21:50 +02:00
2026-10-05 23:42:07 +02:00
2026-10-10 21:23:05 +02:00
2026-10-03 12:16:55 +02:00
2026-10-12 12:41:46 +02:00
2026-10-03 12:16:55 +02:00
2026-05-21 11:39:43 -07:00
2026-05-20 20:57:02 -07:00
2026-09-03 18:52:03 +02:00
2026-05-28 15:01:58 -07:00
2026-10-08 14:34:31 +02:00
2026-06-06 20:46:42 -07:00
2026-06-06 20:46:42 -07:00
2026-07-08 15:13:39 -07:00
2026-09-02 18:34:59 +02:00
2026-10-12 12:41:46 +02:00
2026-05-20 20:57:02 -07:00
2026-10-08 14:34:31 +02:00
2026-10-07 09:25:29 +02:00
2026-05-15 16:21:14 +00:00
2026-05-15 09:16:39 -07:00
2026-09-03 18:52:03 +02:00
2026-09-03 18:52:03 +02:00
2026-10-12 12:41:46 +02:00
2026-10-10 10:58:33 +02:00
2026-10-09 19:58:42 +02:00
2026-10-13 09:01:57 +02:00
2026-09-13 20:37:14 +02:00
2026-10-04 22:11:34 +02:00
2026-10-04 22:11:34 +02:00
2026-05-18 07:36:28 -07:00
2026-09-03 18:52:03 +02:00
2026-10-12 15:24:13 +02:00
2026-10-13 08:35:16 +02:00
2026-09-03 18:52:03 +02:00
2026-06-19 11:37:16 -07:00
2026-10-10 17:39:33 +02:00
2026-10-10 17:39:33 +02:00
2026-10-10 18:20:49 +02:00
2026-10-04 17:15:50 +02:00
2026-10-10 17:39:33 +02:00
2026-10-10 18:20:49 +02:00
2026-10-10 18:20:49 +02:00
2026-05-15 16:21:14 +00:00
2026-10-11 11:17:12 +02:00
2026-09-19 11:44:47 +02:00
2026-10-11 11:17:12 +02:00
2026-09-11 15:07:31 +02:00
2026-09-11 15:07:31 +02:00
2026-09-19 11:44:47 +02:00
2026-10-10 21:22:02 +02:00
2026-10-11 11:17:12 +02:00
2026-09-09 17:58:09 +02:00
2026-09-10 22:30:24 +02:00
2026-10-07 11:20:44 +02:00
2026-10-07 11:20:44 +02:00
2026-10-07 11:20:44 +02:00
2026-10-07 11:20:44 +02:00
2026-06-03 13:58:04 -07:00
2026-06-30 18:21:21 -07:00
2026-10-09 19:58:42 +02:00
2026-10-09 19:58:42 +02:00
2026-10-09 19:58:42 +02:00
2026-10-13 09:01:57 +02:00
2026-05-29 02:42:21 -07:00
2026-10-12 12:41:46 +02:00
2026-10-13 08:35:16 +02:00
2026-10-12 12:41:46 +02:00
2026-10-10 21:21:13 +02:00
2026-09-16 09:02:13 +02:00
2026-10-12 12:41:46 +02:00
2026-06-27 22:03:05 -07:00
2026-09-02 18:34:59 +02:00
2026-10-13 08:35:20 +02:00
2026-10-13 08:35:20 +02:00
2026-10-10 18:20:49 +02:00
2026-06-27 22:03:05 -07:00
2026-06-27 22:03:05 -07:00
2026-06-27 22:03:05 -07:00
2026-06-27 22:03:05 -07:00
2026-10-11 11:28:20 +02:00
2026-10-11 11:28:20 +02:00
2026-10-10 18:20:49 +02:00
2026-10-08 22:16:49 +02:00
2026-10-08 22:16:49 +02:00
2026-06-29 05:48:58 -07:00
2026-09-13 19:59:18 +02:00
2026-09-13 19:59:18 +02:00
2026-09-06 21:11:29 +02:00
2026-09-06 21:11:29 +02:00
2026-09-02 14:21:42 +02:00