diff --git a/rustler_benchmarks/lib/benchmark.ex b/rustler_benchmarks/lib/benchmark.ex index 3baa5778..6bf3a047 100644 --- a/rustler_benchmarks/lib/benchmark.ex +++ b/rustler_benchmarks/lib/benchmark.ex @@ -3,6 +3,15 @@ defmodule Benchmark do def nifstruct_benchmark(_input, _operation), do: error() def nifrecord_benchmark(_input, _operation), do: error() + def encode_tagged_enum(), do: error() + def decode_tagged_enum(_), do: error() + def decode_struct(_), do: error() + def decode_string(_), do: error() + def decode_struct_string(_), do: error() + def decode_term(_), do: error() + def encode_atom(), do: error() + def void(), do: error() + def compare_atom(_), do: error() defp error do :erlang.nif_error(:nif_not_loaded) diff --git a/rustler_benchmarks/lib/benchmark/nif_various.ex b/rustler_benchmarks/lib/benchmark/nif_various.ex new file mode 100644 index 00000000..68d71a10 --- /dev/null +++ b/rustler_benchmarks/lib/benchmark/nif_various.ex @@ -0,0 +1,48 @@ +defmodule Benchmark.NifVarious do + @moduledoc """ + Benchmark the performance of decoding/encoding enums & others. + """ + + defmodule TestStruct do + defstruct [:a, :b, :c, :d] + end + + defmodule TestStructString do + defstruct [:a] + end + + def run do + test_struct = %TestStruct{ + a: "abcd", + b: 6_000_000_000, + c: nil, + d: true + } + + test_struct_string = %TestStructString{ + a: "abcd" + } + + test_struct_enum = {:test_struct, %TestStruct{ + a: "abcd", + b: 6_000_000_000, + c: nil, + d: true + }} + + # Benchmark + Benchee.run(%{ + "encode_atom" => fn -> Benchmark.encode_atom() end, + "compare_atom" => fn -> Benchmark.compare_atom(:test) end, + "void" => fn -> Benchmark.void() end, + "decode_term" => fn -> Benchmark.decode_term("abcd") end, + "struct_string_decode" => fn -> + Benchmark.decode_struct_string(test_struct_string) + end, + "string_decode" => fn -> Benchmark.decode_string("abcd") end, + "struct_decode" => fn -> Benchmark.decode_struct(test_struct) end, + "tagged_enum_decode" => fn -> Benchmark.decode_tagged_enum(test_struct_enum) end, + "tagged_enum_encode" => fn -> Benchmark.encode_tagged_enum() end + }) + end +end diff --git a/rustler_benchmarks/native/benchmark/src/lib.rs b/rustler_benchmarks/native/benchmark/src/lib.rs index f9cc5a4c..2589025a 100644 --- a/rustler_benchmarks/native/benchmark/src/lib.rs +++ b/rustler_benchmarks/native/benchmark/src/lib.rs @@ -1,7 +1,20 @@ mod nif_record; mod nif_struct; +mod nif_various; rustler::init!( "Elixir.Benchmark", - [nif_struct::benchmark, nif_record::benchmark] + [ + nif_struct::benchmark, + nif_record::benchmark, + nif_various::encode_tagged_enum, + nif_various::decode_tagged_enum, + nif_various::decode_struct, + nif_various::decode_struct_string, + nif_various::decode_string, + nif_various::decode_term, + nif_various::void, + nif_various::encode_atom, + nif_various::compare_atom + ] ); diff --git a/rustler_benchmarks/native/benchmark/src/nif_various.rs b/rustler_benchmarks/native/benchmark/src/nif_various.rs new file mode 100644 index 00000000..79772272 --- /dev/null +++ b/rustler_benchmarks/native/benchmark/src/nif_various.rs @@ -0,0 +1,110 @@ +use rustler::{atoms, Atom, NifResult, Term}; +use rustler::{NifStruct, NifTaggedEnum}; +use std::collections::HashMap; + +atoms! { + test_a, + test_b, + test +} + +#[derive(NifStruct)] +#[module = "Benchmark.NifVarious.TestStructString"] +pub struct TestStructString { + a: String, +} + +#[derive(NifStruct)] +#[module = "Benchmark.NifVarious.TestStruct"] +pub struct TestStruct { + a: String, + b: i64, + c: Option, + d: bool, +} + +#[derive(NifTaggedEnum)] +pub enum TaggedEnum { + UnitA, + UnitB, + UnitC, + UnitD, + UnitE, + UnitF, + GenericA(String), + GenericB(String), + GenericC(String), + GenericD(String), + GenericE(String), + GenericF(String), + GenericG(String), + GenericH(String), + GenericI(String), + GenericJ(String), + Tuple((String, i64)), + List(Vec), + Map(HashMap), + String(String), + Int(i32), + TestStruct(TestStruct), +} + +#[rustler::nif] +pub fn decode_term(input: Term) -> NifResult { + Ok(!input.is_atom()) +} + +#[rustler::nif] +pub fn decode_string(input: String) -> NifResult { + Ok(!input.is_empty()) +} + +#[rustler::nif] +pub fn decode_struct_string(input: TestStructString) -> NifResult { + Ok(!input.a.is_empty()) +} + +#[rustler::nif] +pub fn decode_struct(input: TestStruct) -> NifResult { + Ok(input.d) +} + +#[rustler::nif] +pub fn decode_tagged_enum(input: TaggedEnum) -> NifResult { + match input { + TaggedEnum::UnitA => Ok(true), + _ => Ok(false), + } +} + +#[rustler::nif] +pub fn encode_tagged_enum() -> TaggedEnum { + TaggedEnum::TestStruct(TestStruct { + a: "abc".to_string(), + b: 124, + c: None, + d: true, + }) +} + +#[rustler::nif] +pub fn void() {} + +#[rustler::nif] +pub fn encode_atom() -> Atom { + test_a() +} + +#[rustler::nif] +pub fn compare_atom(a: Atom) -> Atom { + if a == test_a() { + return test_a(); + } + if a == test_a() { + return test_a(); + } + if a == test_a() { + return test_a(); + } + a +}