Rustly::Core is the performance-heavy foundation of the Rustly stack. It compiles model schemas, validates payloads outside the GVL, and materialises Ruby objects with minimal crossing overhead.
- Schema compilation – crushes the Ruby AST into a compact
CompiledSchematyped object. - Validation & coercion – launches heavy lifting in Rust without the GVL and returns an
ErrorSeton failure. - Materialisation – materialises Ruby structs directly;
@attributesis only built whenstore_attributes: true. - Ractor safety – typed data objects avoid storing Ruby values inside Rust heaps, so you can run flat-out across threads.
- Ruby 3.2 – 3.4 (CI covers Linux and macOS).
- Rust 1.85 (minimum supported Rust version).
- Bundler 2.5 or newer.
bundle install
bundle exec rake compile
bundle exec rspec
cargo test --manifest-path Cargo.tomlrequire "rustly/core"
schema_ast = {
type: :struct,
fields: [[:required, :email, :string, { format: :email }]],
extra: :forbid
}
compiled = Rustly::Core.compile(schema_ast)
instance = Rustly::Core.build(compiled, { email: "[email protected]" }, Struct.new(:email))
puts "Materialized: #{instance.inspect}"Rustly::Core.build returns the materialized instance on success and raises Rustly::Core::ValidationError
when validation fails. The raised exception exposes an ErrorSet via #errors. By default the object is
left unfrozen (freeze: :none) and does not allocate @attributes; enable the relevant switches when you
need them.
Rustly::Core.compile merges user options with Rustly::Core::DEFAULT_OPTIONS. Key switches:
strict(default:false) — enforce strict coercions.extra— extras policy (:forbid,:ignore,:allow).input_mode—:auto,:ruby, or:json.freeze(default::none) — choose between:none,:shallow,:deep.store_attributes(default:false) — capture the raw payload in@attributes.
ext/rustly_core– Rust sources (cdylib) and Cargo configuration.lib/rustly– Ruby wrapper and helpers (DEFAULT_OPTIONS, normalised options).spec/– RSpec smoke tests..github/workflows/ci.yml– CI for Linux/macOS, Ruby 3.2–3.4,rustfmt,clippy, andcargo-deny.
bundle exec rake compile
bundle exec rspec
cargo test --manifest-path Cargo.toml
cargo fmt --manifest-path Cargo.toml -- --check
cargo clippy --manifest-path Cargo.toml --all-targets -- -D warnings
bundle exec rubocop
cargo deny check --manifest-path Cargo.tomlbundle exec rake lint runs RuboCop together with cargo fmt and cargo clippy.
- Date: October 24, 2025
- Ruby: 3.4.7 (2025-10-08) +PRISM [x86_64-linux]
- OS: Linux 6.14.0-34-generic
- Commands:
bin/compare_models,bundle exec ruby bench/throughput.rb --count 10000 --rounds 5
- Dataset: 100,000 payloads that follow the
SCHEMAconstant inbin/compare_models(symbol keys, frozen tag arrays). - Rustly options:
freeze: :none,store_attributes: false. - Memory allocations (benchmark-memory, single threaded):
| Implementation | Allocated Memory | Objects Allocated | Strings Allocated |
|---|---|---|---|
| Rustly::Core | 28.000 MB | 500,000 | 50 |
| Dry::Struct | 24.006 MB | 300,067 | 35 |
| SmartCore::ValueObject | 216.000 MB | 3,900,000 | 5 |
- Single-thread throughput (Benchmark.bmbm, real time):
| Implementation | Real Time (s) |
|---|---|
| Rustly::Core | 0.123 |
| Dry::Struct | 0.437 |
| SmartCore::ValueObject | 1.952 |
- Parallel throughput with 10 threads (Parallel + Benchmark.bmbm, real time):
| Implementation | Real Time (s) |
|---|---|
| Rustly::Core (10 threads) | 0.236 |
| Dry::Struct (10 threads) | 0.474 |
| SmartCore::ValueObject (10 threads) | 1.429 |
Rustly::Core still clocks in 3.6× faster than Dry::Struct and 15.9× faster than SmartCore::ValueObject in single-threaded runs. It chews through the workload with 28 MB of allocations—just 1.17× over Dry::Struct while burning 7.7× less than SmartCore. Crank the dial to 10 threads and Rustly pulls further ahead, finishing 2× faster than Dry and 6× faster than SmartCore while staying allocation-efficient.
- Options:
--count 10000,--rounds 5, JSON mode enabled (default). - Dataset: generated map of 10,000 keys to nested structs (see
bench/throughput.rb).
| Measurement | Avg (s) | Min (s) | Max (s) |
|---|---|---|---|
| prepare_input(:ruby) | 0.004 | 0.004 | 0.005 |
| prepare_input(:json) | 0.001 | 0.000 | 0.001 |
| validate_no_gvl | 0.011 | 0.010 | 0.012 |
- All rounds completed without validation failures; the helper raises if any preparation or validation step returns an error tuple.
Rustly::Core is released under the MIT License.
