Ratchets Run Faster with Resharp

Switching from the regex crate in Rust to Resharp makes Ratchets run 15% faster on the Sculptor codebase

by on

Yesterday, I released Ratchets v0.4.0, a breaking change which switched the regular expression engine from the widely-used Rust regex crate to Resharp. Although this was originally driven by my desire to support lookaround assertions, I noticed a healthy speed-up when using the new version of Ratchets on the Sculptor codebase. With no other changes, Ratchets is now approximately 15% faster on our codebase.

Fig. 1. A comparison of run times of `ratchets check` on Sculptor, using `Resharp` vs `regex`

What is a ratchet?

I was first introduced to the concept of ratchets by this qntm blog article, which describes a system to prevent developers from adding more instances of a particular pattern to a codebase. A ratchet system tolerates existing instances of a forbidden pattern by maintaining a count, and it forbids increases while enforcing that decreases are recorded and committed. The count is therefore encouraged to decrease over time, tightening the strictness on the codebase–hence the name. The ratchet system saves you the effort of migrating the entire codebase whenever you introduce a new rule.

At Imbue, we’ve embraced ratchets since before the dawn of agentic coding, and we started out deploying them in the fashion above. That is, we used ratchets to encourage our human developers to adhere to our evolving style guide and to ensure that our code evolved in a good direction. But as agentic engineering has taken off, we’ve found that the use-case for ratchets has changed. Today, it is fairly simple to launch a swarm of agents to migrate your entire codebase away from a bad pattern, and so the use-case for ratchets would apparently be removed.

However, I’ve found that there’s still a good reason to use a ratchet system. Although I can’t speak for Fable because my time with it was extremely brief, my experience with other coding agent models testifies poorly to their ability to adhere to a style guide. Because their tendency is to generate code in line with their training set, you find yourself in tension with that tendency when you attempt to constrain them with elaborate rules. This costs input tokens, and using an agent-as-judge to validate style is even more expensive. If you still care about code style—as we do—then a ratchet enforcement system which flags problems to the agent can be very helpful.

Ratchets are even more useful when you really need that escape hatch to allow a forbidden pattern into your codebase. One example we find is type-checker suppressions. A coding agent’s propensity might be to reach for # pyrefly: ignore rather than understanding the type boundary. However, sometimes that might be the right decision, and the coding agent itself does not have sufficient context and judgement to come to the right decision. In this case, you can separate the judgement of whether to use the expedient path from the coding agent, and leave it up to a planning agent. Only the planning agent has the authority to bump the ratchet, and it does that with a wider perspective than a particular coding agent. In this way, certain language features can be used only sparingly, if there is no other way to achieve a goal. This is the approach I’ve taken in Rust Bucket, my agentic workflow and scaffold for Rust programs.

How Ratchets uses regular expressions

I could dedicate a separate article to the implementation details of Ratchets, so to keep this short, it has two mechanisms for detecting forbidden patterns:

  • abstract syntax tree queries,
  • and regular expressions

I decided to implement abstract syntax tree queries via tree-sitter since they are much more precise than regular expressions. For example, regular expressions can be sensitive to formatting and line-wrapping, which were specific issues that led to miscounting by our previous implementation. The tree-sitter queries are syntax-aware, and are robust to these kinds of problems.

However, there were still a few rules that were best expressed as regular expressions–most commonly rules about comment style. I’d initially used the regex crate, but I was surprised to find that it did not support proper lookaround. It was this need, rather than a desire for performance optimization, that led me to look into replacing it with Resharp. I’d remembered reading their article on Hacker News and had been pleased to see they’d released a Rust port.

An agent was able to perform the replacement with ease, and the copious tests we had on the codebase gave me confidence. Once the replacement was completed, I wanted to check whether there was going to be a performance difference. I was very pleased to find that replacing regex with Resharp, and no other changes, made Ratchets run significantly faster on the Sculptor codebase.

Not a conclusion

I don’t have a polished final conclusion to leave with you, because this space is evolving so quickly and I’m still working through many of these thoughts in my head. But in lieu of that, here are a few observations:

  • If you have a Rust program that makes heavy use of regular expressions, you should evaluate Resharp.
  • While agentic engineering is improving by leaps and bounds, the scaffolding and tools you give your agents dramatically improve your outcomes for the same budget of human attention and tokens.
  • Ratchets is open source and permissively licensed. Please give it a look and see if it’s for you!