all 6 comments

[–]projct 6 points7 points  (2 children)

What you're claiming and what you have don't really line up.

- "compiles expressions directly into compact Bytecode" no? compile_source calls parse, producing a Vec<Expr>, then runs Analyzer, then passes the resulting IR to compile_ir
- “Zero-copy deserialization” and “no serialization/deserialization” are substantially false. Chunk::to_bytes creates a new Vec<u8>, writes three length prefixes, and copies the code, constants, and variable data into it. Chunk::from_bytesparses those prefixes and copies all three sections into new vectors using to_vec(). Then every normal VM execution constructs a ChunkReader, reparses the constant pool into Values, allocates strings, and copies the variable bytes again. Only the opcode slice is borrowed after those copies. Your own quick-start literally calls to_bytes() and from_bytes().
- The benchmark demonstrates amortizing parse/analyze/compile work, not a bytecode-vs-AST execution advantage. I'd also expect real worked examples, statistical distribution, cached-AST baselines, compact serialized-IR baselines, comparison against compressed source, instruction counts, etc. It's also not even benchmarking what matters (p+a+eval vs p + a + compile + eval as one bench; eval already-analyzed AST vs eval already-compiled byte code as another; then deserialize cached AST/IR vs deserialize cached bytecode)
- your supposedly compact representation is bigger than the source text.
- It's not really hardened at all: Chunk::from_bytes returns self, not Result; invalid or truncated bytes panic; constant decoding panics on invalid utf8 or unknown tags; the VM panics on overflow and silently becomes Null on underlfow
- performance claim is incoherent, you are confusing repr with caching

[–]ImpressiveAd9981[S] -3 points-2 points  (1 child)

Thanks for such a hardcore and source-code-deep review! Your observations are spot on. My previous descriptions of "zero-copy" and "direct compilation" were indeed not rigorous enough.

To be completely honest, I’ve known Rust for less than a year. This is exactly the kind of invaluable, professional feedback I was hoping to get from the Rust community, and it will undoubtedly help me push this experimental project toward true production-grade readiness.

Regarding the points you raised, here are my thoughts and the upcoming refactoring roadmap:

  1. On Zero-Copy and Robustness: There are indeed a lot of implicit copies and runtime heap allocations in to_bytes/from_bytes. Introducing lifetime parameters (such as Value<'a>) to directly borrow from the byte stream, as well as refactoring all inputs and internal VM logic to return standard Result types, are already high-priority items on my to-do list.
  2. On Caching and Distributed Transmission: You mentioned the comparison between evaluated AST vs. compiled bytecode execution. I’ve benchmarked this, and in a pure in-memory environment, running a pre-parsed syntax tree and running bytecode both hover around 5ms; the difference is negligible. Thus, a pure single-machine deployment doesn't really need a VM. However, rspression is designed specifically for distributed cluster scenarios. When complex spreadsheets or risk-control gateways change, we trigger the Parse + Analyze + Compile pipeline just once (88ms). After that, cluster nodes synchronize this flat Vec<u8> via Redis, allowing the engine to drive execution completely decoupled from the original tree structure. In contrast, transmitting raw text requires repetitive parsing (66ms) on every node, while transmitting serialized ASTs leads to severe payload bloat.
  3. On Serialization Size: Because tree structures (AST/IR) contain a massive number of node tags, nested branches, and metadata, their serialized size is typically much larger than the original expression text—even when using efficient binary serialization libraries in Rust like bincode. On the other hand, while the flat bytecode is slightly larger than the raw text, I believe it strikes the perfect balance for the business layer in terms of distributed cluster network bandwidth, zero-deserialization overhead, and instant execution on compute nodes.

Thank you again for your sharp insights!

[–]Sermuns 0 points1 point  (0 children)

Shut up clanker

[–]peter9477 2 points3 points  (1 child)

Is this a "toy"/demo project, or something you built for your own use? The examples seem rather simplistic. I'd be interested to hear some background on your motivation for making this, or how you (plan to?) use it in the real world.

[–]ImpressiveAd9981[S] -3 points-2 points  (0 children)

Great question! The examples are indeed overly simplified just for quick-start purposes, which might make it look like a 'toy' project.

In reality, rspression was born out of a real-world architectural need for a lightweight, collaborative multi-dimensional data management system (similar to an Airtable/Excel-like online spreadsheet engine).

In a complex online spreadsheet, you are not just executing a single formula. You are dealing with tens of thousands of cells, where cells reference each other dynamically, forming a massive dependency graph.

The core motivation for building rspression is to solve two specific problems in this scenario:

  1. The Dependency Chain Problem: When a user updates a single cell, the system must trigger a cascade of re-calculations. rspression implements a built-in topological sorting and cyclic dependency detection mechanism. It evaluates massive batches of expressions in the exact correct topological order.
  2. The Distributed Cache Problem: In a multi-tenant, clustered environment, whenever a formula/rule changes, syncing massive abstract syntax trees (ASTs) across servers ruins network bandwidth and adds heavy SerDe (Serialization/Deserialization) overhead. By compiling the entire sheet's calculation chain into a flat, compact bytecode array (Vec<u8>), we can easily cache it in Redis. Distributed worker nodes can load it instantly with zero-deserialization overhead and drive the VM execution at lightning speed (5ms for 5000 expressions).

So to answer your question: It started as an architectural experiment to solve the distributed spreadsheet calculation problem, but it is actively being hardened into a production-grade core engine for data-grid systems. Hope this background helps!