Repository navigation
Optimize Messagebus::Message.decode method - #383
moberegger wants to merge 4 commits into
Conversation
There was a problem hiding this comment.
🔵 Needs a closer look
Byte-oriented parsing lacks requested multibyte channel test coverage.
Pull request overview
Optimizes MessageBus::Message.decode using byte-oriented operations and fewer allocations.
Changes:
- Replaces character-based indexing and slicing with byte-based equivalents.
- Avoids unnecessary substring allocation and substitution work.
- Requests multibyte channel round-trip coverage.
File summaries
| File | Description |
|---|---|
lib/message_bus/message.rb |
Optimizes message decoding while preserving behavior. |
Review details
Suppressed comments (1)
lib/message_bus/message.rb:10
- The byte-based parsing path is only directly covered by an ASCII round-trip (
backend_spec.rb:83-85). Please add a round-trip case with a multibyte channel (ideally also containing|) so the byte offsets andbytesliceboundaries are protected against encoding regressions.
s1 = encoded.byteindex("|")
s2 = encoded.byteindex("|", s1 + 1)
s3 = encoded.byteindex("|", s2 + 1)
- Files reviewed: 1/1 changed files
- Comments generated: 0
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
I can take a closer look at this. Looks like it might just be some additional test coverage? Wouldn't hurt to do the extra due diligence (... and I suppose there might be some nuance here that I am missing). |
|
@SamSaffron Added some extra tests, including one for multi-byte channels. |
Saw this coming up as a hotspot in our production profiles.
Found a few optimization candidates that looked lower risk to implement:
encoded.to_iinstead ofencoded[0, s1 + 1].to_i.String#to_iwill stop parsing at the first non-numeric character, so calling it on the full string yields the same result as extracting a substring first. This eliminates a string allocation.byteindexinstead ofindex. Since the pipe delimiter|is a single-byte ASCII character, this produces the same result but skips character-encoding boundary checks (At least that is my undertanding). (Note: I believe Ruby 3.2+ is required forbyteindex, but this is specified is the minimum Ruby version in the gemspec.)bytesliceinstead of[]. If the encoded format is always ASCII-safe,byteslicecan skip the character-encoding boundary checks thatString#[]performs. This is a cheaper operation for the same result.encoded.bytesizeinstead ofencoded.size. This avoids a character-length scan on the string.include?guard beforegsub!. Saves on agsub!in situations where there is nothing to substitute. I am not sure how common the$$123$$escape sequence will be present, but this will skip that overhead when it's not necessary.Benchmarks against
Messagebus::Message.decode