Repository navigation
Tracing zipper - #166
Tracing zipper#166luketpeterson wants to merge 4 commits into
Conversation
Bench A/B vs base: donejob log · 2026-10-28 08:57:28 UTC base fb979b4 → head 10f93e2, 3 round(s), median of each run averaged; negative is faster
38 case(s) moved more than 5%
Full tables per bench are in the job log and the bench-out artifact. |
|
I'm guessing this is fine to merge because it doesn't interfere with any existing functionality. But I'll keep it as a PR until Matt finalizes the curriculum in case somebody wants to improve or extend the functionality. |
|
From @Adam-Vandervorst on discord:
The TraceZipper in the current PR is already a drop-in replacement for another zipper type. So the API the user sees isn't duplicated. As far as separating the enum-based operation format from the API, we still need a format that can represent every operation and its args in a file or buffer, so I don't see how we get away from that. If I'm understanding the comment correctly, the proposal is for an EchoZipper (I think this is a more appropriate name than TeeZipper because it would need to privilege the primary zipper as the source of truth, and the secondary would just be an observer) and then a TraceZipper or "RecorderZipper" that blindly records the operations but maintains no state. Is this a correct summary of the proposal? The 2-object split (EchoZipper + RecorderZipper) comes with some warts we'd need to handle.
If that's the correct understanding, my question is what is enabled by splitting things into 2 objects? We'd get an EchoZipper that could have uses outside recording a trace - but it's quite a lot more surface area and I don't see it simplifying anything. |
|
I'd like to have low-overhead recording for specific sets of methods. |
Currently ACT only stores u64s and paths doesn't store anything (unless you added something on a private branch. But perhaps this is the time to define a val on-disk format. I filed #170 I don't want to deal with this now, but it makes sense to handle it eventually. |
Making trace format more compact and faster to encode, with bitcode, so now it wouldn't be hideous to use in a production setting although not optimi zed for perf Adding multi-target support so zippers can target any implementor of Write for their trace output
|
In 0e83abd I made the trace format a lot more compact and cheaper to write (although I didn't benchmark or optimize the code, I just got rid of obvious slow stuff) I also added multiple target support so there is no longer a single magic static state holding the output state, in response to Igor's point in the meeting. It still uses thread-locals behind the scenes because that was the most efficient way to preserve the order of multiple zippers on a single thread. While cross-zipper order only technically matters for correctness during operations, it is desirable to keep things in the order they occurred in, where possible. Lastly I got rid of non () and u64 V types, in anticipation of a better crate-wide solution for serializing Vs. #170 |
Differential fuzz vs Lean model: successjob log · 2026-10-28 08:51:06 UTC WARNING: 1 new divergence(s) relative to base Base was built with its own harness and model (head's did not build against it), so harness changes may show up as differences. crate: 20000 inputs, seed 7agree = model and crate match; known = the divergence matches a classified bug in differential.py; new = it matches none. Only the new set is compared input by input below.
1 input(s) diverge on head but not on base; 0 diverge on base but not on head. Known-class hits that changed
Newly diverging inputs (head only): 1 input(s), 1 kind(s)
Reproducers: first 1 distinct kind(s), shrunk
|
| side | agree | known | new divergences |
|---|---|---|---|
| head | 3570/5000 | 1430 | 0 |
| base | 3568/5000 | 1432 | 0 |
0 input(s) diverge on head but not on base; 0 diverge on base but not on head.
Known-class hits that changed
| known class | base | head |
|---|---|---|
| ACTZipper::val_count() counts from the zipper root, not the focus [act: val_count_ignores_focus] | 1431 | 1430 |
| an algebraic op keeps a dangling child the spec drops: an empty child node meets/subtracts to itself | 1 | 0 |
|
OK. after thinking about this for a while, I think I'm unhappy with the API it's a bit too unwieldy. |
TraceZipper for debugging and tool to render animation from trace