Skip to content

Commit

Permalink
rune: Switch to storing values inline
Browse files Browse the repository at this point in the history
  • Loading branch information
udoprog committed Jul 28, 2024
1 parent a32e90a commit 0d1d8c3
Show file tree
Hide file tree
Showing 55 changed files with 3,643 additions and 2,399 deletions.
7 changes: 6 additions & 1 deletion benches/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,17 @@ publish = false

[dependencies]
rune = { path = "../crates/rune", features = ["bench", "capture-io"] }
rhai = "1.19.0"

tokio = { version = "1.28.1", features = ["macros"] }
criterion = "0.4.0"
anyhow = "1.0.71"
futures-executor = "0.3.28"

[[bench]]
name = "bench_main"
name = "main"
harness = false

[[bench]]
name = "comparison"
harness = false
74 changes: 74 additions & 0 deletions benches/benches/comparison.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use rune::{BuildError, Context, Diagnostics, Options, Source, Sources, Vm};
use std::any::Any;
use std::sync::Arc;

pub(crate) fn vm(
context: &Context,
sources: &mut Sources,
diagnostics: &mut Diagnostics,
) -> Result<Vm, BuildError> {
let mut options = Options::default();
options
.parse_option("function-body=true")
.expect("failed to parse option");

let unit = rune::prepare(sources)
.with_context(context)
.with_diagnostics(diagnostics)
.with_options(&options)
.build()?;

let context = Arc::new(context.runtime()?);
Ok(Vm::new(context, Arc::new(unit)))
}

pub(crate) fn sources(source: &str) -> Sources {
let mut sources = Sources::new();

sources
.insert(Source::new("main", source).expect("Failed to construct source"))
.expect("Failed to insert source");

sources
}

macro_rules! rune_vm {
($($tt:tt)*) => {{
let context = rune::Context::with_default_modules().expect("Failed to build context");
let mut diagnostics = Default::default();
let mut sources = $crate::sources(stringify!($($tt)*));
$crate::vm(&context, &mut sources, &mut diagnostics).expect("Program to compile successfully")
}};
}

macro_rules! rhai_ast {
($($tt:tt)*) => {{
let mut engine = $crate::rhai::Engine::new();
engine.set_optimization_level($crate::rhai::OptimizationLevel::Full);
let ast = engine.compile(stringify!($($tt)*)).unwrap();
$crate::RhaiRunner { engine, ast }
}};
}

pub(crate) struct RhaiRunner {
pub(crate) engine: crate::rhai::Engine,
pub(crate) ast: crate::rhai::AST,
}

impl RhaiRunner {
fn eval<T: Any + Clone>(&self) -> T {
self.engine.eval_ast(&self.ast).unwrap()
}
}

pub(crate) mod rhai {
pub(crate) use ::rhai::{Engine, OptimizationLevel, AST};
}

mod comparisons {
pub mod primes;
}

criterion::criterion_main! {
comparisons::primes::benches,
}
77 changes: 77 additions & 0 deletions benches/benches/comparisons/primes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
use criterion::Criterion;
use rune::Hash;

criterion::criterion_group!(benches, entry);

fn entry(b: &mut Criterion) {
let mut group = b.benchmark_group("primes");

group.bench_function("rhai", |b| {
let ast = rhai_ast! {
const MAX_NUMBER_TO_CHECK = 10_000;

let prime_mask = [];
prime_mask.pad(MAX_NUMBER_TO_CHECK, true);

prime_mask[0] = false;
prime_mask[1] = false;

let total_primes_found = 0;

for p in 2..MAX_NUMBER_TO_CHECK {
if prime_mask[p] {
total_primes_found += 1;
let i = 2 * p;

while i < MAX_NUMBER_TO_CHECK {
prime_mask[i] = false;
i += p;
}
}
}

total_primes_found
};

b.iter(|| {
let value = ast.eval::<i64>();
assert_eq!(value, 1229);
value
});
});

group.bench_function("rune", |b| {
let mut vm = rune_vm! {
const MAX_NUMBER_TO_CHECK = 10_000;

let prime_mask = [];
prime_mask.resize(MAX_NUMBER_TO_CHECK, true);

prime_mask[0] = false;
prime_mask[1] = false;

let total_primes_found = 0;

for p in 2..MAX_NUMBER_TO_CHECK {
if prime_mask[p] {
total_primes_found += 1;
let i = 2 * p;

while i < MAX_NUMBER_TO_CHECK {
prime_mask[i] = false;
i += p;
}
}
}

total_primes_found
};

b.iter(|| {
let value = vm.call(Hash::EMPTY, ()).unwrap();
let value: i64 = rune::from_value(value).unwrap();
assert_eq!(value, 1229);
value
})
});
}
File renamed without changes.
33 changes: 0 additions & 33 deletions benches/benches/primes.rn

This file was deleted.

2 changes: 1 addition & 1 deletion crates/rune-alloc/src/hashbrown/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2163,7 +2163,7 @@ impl<K, V, S, A: Allocator> HashMap<K, V, S, A> {
/// Unless you are in such a situation, higher-level and more foolproof APIs like
/// `get` should be preferred.
///
/// Immutable raw entries have very limited use; you might instead want `raw_entry_mut`.
/// Inline raw entries have very limited use; you might instead want `raw_entry_mut`.
///
/// # Examples
///
Expand Down
2 changes: 1 addition & 1 deletion crates/rune-alloc/src/slice/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::alloc::SizedTypeProperties;
use crate::hint::assume;
use crate::ptr::{self, invalid, invalid_mut, NonNull};

/// Immutable slice iterator
/// Inline slice iterator
///
/// This struct is created by the [`iter`] method on [slices].
///
Expand Down
4 changes: 2 additions & 2 deletions crates/rune-macros/src/from_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ impl Expander {
let (expanded, expected) = match &st.fields {
syn::Fields::Unit => {
let expanded = quote! {
#type_value::EmptyTuple => {
#type_value::Unit => {
#vm_result::Ok(Self)
}
#type_value::EmptyStruct(..) => {
Expand All @@ -44,7 +44,7 @@ impl Expander {
let expanded = self.expand_unnamed(f)?;

let expanded = quote! {
#type_value::EmptyTuple => {
#type_value::Unit => {
let tuple = #tuple::new(&[]);
#vm_result::Ok(Self(#expanded))
}
Expand Down
10 changes: 9 additions & 1 deletion crates/rune/src/cli/benches.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,14 @@ struct Time(u128);

impl fmt::Display for Time {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}ns", self.0)
if self.0 >= 1_000_000_000 {
write!(f, "{:.3}s", self.0 as f64 / 1_000_000_000.0)
} else if self.0 >= 1_000_000 {
write!(f, "{:.3}ms", self.0 as f64 / 1_000_000.0)
} else if self.0 >= 1_000 {
write!(f, "{:.3}µs", self.0 as f64 / 1_000.0)
} else {
write!(f, "{}ns", self.0)
}
}
}
8 changes: 4 additions & 4 deletions crates/rune/src/cli/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::cli::{
use crate::compile::FileSourceLoader;
use crate::doc::TestParams;
use crate::modules::capture_io::CaptureIo;
use crate::runtime::{Value, ValueKind, Vm, VmError, VmResult};
use crate::runtime::{Mutable, OwnedValue, Value, Vm, VmError, VmResult};
use crate::termcolor::{Color, ColorSpec, WriteColor};
use crate::{Diagnostics, Hash, Item, ItemBuf, Source, Sources, Unit};

Expand Down Expand Up @@ -458,12 +458,12 @@ impl TestCase {
capture_io.drain_into(&mut self.output)?;

self.outcome = match result {
VmResult::Ok(v) => match v.take_kind()? {
ValueKind::Result(result) => match result {
VmResult::Ok(v) => match v.take_value()? {
OwnedValue::Mutable(Mutable::Result(result)) => match result {
Ok(..) => Outcome::Ok,
Err(error) => Outcome::Err(error),
},
ValueKind::Option(option) => match option {
OwnedValue::Mutable(Mutable::Option(option)) => match option {
Some(..) => Outcome::Ok,
None => Outcome::None,
},
Expand Down
8 changes: 7 additions & 1 deletion crates/rune/src/compile/context_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,13 @@ impl fmt::Display for ContextError {
hash,
item_hash,
} => {
write!(f,"Type hash mismatch for `{type_info}`, from module is `{hash}` while from item `{item}` is `{item_hash}`. A possibility is that it has the wrong #[rune(item = ..)] setting.")?;
let expected = item.parent().unwrap_or_default();

write! {
f,
"Type hash mismatch for `{type_info}`, from module is `{hash}` while from item `{item}` is `{item_hash}`.\n\
You might not have the #[rune(item = {expected})] attribute set."
}?;
}
ContextError::StaticTypeHashMismatch {
type_info,
Expand Down
7 changes: 3 additions & 4 deletions crates/rune/src/compile/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use crate::parse::{Expectation, IntoExpectation, LexerMode};
use crate::query::MissingId;
use crate::runtime::debug::DebugSignature;
use crate::runtime::unit::EncodeError;
use crate::runtime::{AccessError, RuntimeError, TypeInfo, TypeOf, ValueKind, VmError};
use crate::runtime::{AccessError, RuntimeError, TypeInfo, TypeOf, VmError};
use crate::shared::CapacityError;
#[cfg(feature = "std")]
use crate::source;
Expand Down Expand Up @@ -191,16 +191,15 @@ impl Error {
}

/// An error raised when we expect a certain constant value but get another.
pub(crate) fn expected_type<S, E>(spanned: S, actual: &ValueKind) -> Self
pub(crate) fn expected_type<E>(spanned: impl Spanned, actual: TypeInfo) -> Self
where
S: Spanned,
E: TypeOf,
{
Self::new(
spanned,
IrErrorKind::Expected {
expected: E::type_info(),
actual: actual.type_info(),
actual,
},
)
}
Expand Down
8 changes: 4 additions & 4 deletions crates/rune/src/compile/ir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ use crate::indexing::index;
use crate::macros::MacroContext;
use crate::parse::NonZeroId;
use crate::query::Used;
use crate::runtime::{Value, ValueKind};
use crate::runtime::{Inline, Value};

pub(crate) use self::compiler::Ctxt;
pub(crate) use self::eval::{eval_ir, EvalOutcome};
Expand Down Expand Up @@ -537,9 +537,9 @@ impl IrAssignOp {
where
S: Copy + Spanned,
{
if let ValueKind::Integer(target) = &mut *target.borrow_kind_mut().with_span(spanned)? {
if let ValueKind::Integer(operand) = *operand.borrow_kind_ref().with_span(spanned)? {
return self.assign_int(spanned, target, operand);
if let Some(Inline::Integer(target)) = target.as_inline_mut().with_span(spanned)? {
if let Some(Inline::Integer(operand)) = operand.as_inline().with_span(spanned)? {
return self.assign_int(spanned, target, *operand);
}
}

Expand Down
Loading

0 comments on commit 0d1d8c3

Please sign in to comment.