Trouble Benchmarking actix_web api with Criterion - rust

I have been trying to add benchmarking using the Criterion crate to my actix_web application. I have been struggling to get it to work because the AsyncExecutor trait is not implemented for tokio 0.2.x. I tried implementing the trait for the actix_rt runtime but ran into issues there as well, code below
impl AsyncExecutor for ActixRuntime {
fn block_on<T>(&self, future: impl Future<Output=T>) -> T {
self.rt.block_on(future)
}
}
pub struct ActixRuntime {
rt: actix_rt::Runtime,
}
impl ActixRuntime {
pub fn new() -> Self {
ActixRuntime {
rt: actix_rt::Runtime::new().unwrap(),
}
}
}
this errors out because the block_on function for actix_rt (and tokio 0.2.x) is has a signature of
block_on(&mut self, ...) -> ... { ... }
So I cannot implement the trait since the trait has an immutable reference.
Before I dig myself further into trying to make this work I want to ask if what I am attempting is possible. Is there a way to use Criterion with actix? Or is this impossible as of now? If it is not possible are there any other frameworks available or should I look at solutions outside the rust toolchain?
Thanks for any advice or help, links and examples welcome!
Cheers!

actix-rt v2's block_on method takes &self now after upgrading to tokio 1.0. Upgrading should fix your issue:
// pin your deps: https://github.com/actix/actix-web/issues/1944
actix-rt = "=2.0.0-beta.2"
actix-web = "4.0.0-beta.1"
actix-service = "=2.0.0-beta.3"
If upgrading is not an option, you can use an interior mutability wrapper, such as RefCell:
impl AsyncExecutor for ActixRuntime {
fn block_on<T>(&self, future: impl Future<Output=T>) -> T {
self.rt.borrow_mut().block_on(future)
}
}
pub struct ActixRuntime {
rt: RefCell<actix_rt::Runtime>,
}
impl ActixRuntime {
pub fn new() -> Self {
ActixRuntime {
rt: RefCell::new(actix_rt::Runtime::new().unwrap())
}
}

There doesn't seem like a good way to do this. There are no stable actix versions supporting actix_rt 2.0.x (though it would fix the mutability conflicts in the AsyncExecutor). As of right now actix-web 4.0.x is in beta and too unstable for my existing application (causes all sorts of issues when used). For now I will wait until actix-web 4.0.0 is released and stable to implement benchmarks for my api.

Related

Porting an OOP ObserverPattern to Rust

I am porting an SDK from Java&Golang to Rust. These SDKs work auto-generating boilerplate code like this using templates (In java using OOP and in Golang using Reflection):
trait RPC {
fn decode(&self, frame: &Frame) -> ();
fn execute(&self) -> ();
}
struct MyRPC{
decoded: String
}
impl MyRPC for RPC{
//default implementations of decode and execute methods.
}
I would like that my user could do something like this so the only code that they need to write is the business logic:
include("autogeneratedCode")
impl MyRPC{
fn execute(&self){
//Do something with &self.decoded
}
}
execute() function should be called using an observer pattern:
let subscribers: HashMap<String, Box<dyn RPC>>
pub fn publish(&self, frame: &Frame) -> () {
for subscriber in self.subscribers.iter() {
let mut cloned_subscriber = subscriber.1.clone(); // <<1
cloned_subscriber.parse(frame); // <<2
cloned_subscriber.execute(); // <<3
}
}
I'm not able to make this code work in Rust having this problems:
variable does not need to be mutable Note: #[warn(unused_mut)]on by default Help: remove thismut. I guess the problem is that subscriber.1.clone() is a Box<dyn &RPC> and being a reference we should not mutate it?
cannot borrow **cloned_subscriberas mutable, as it is behind a&reference [E0596]cloned_subscriberis a& reference, so the data it refers to cannot be borrowed as mutable.
This is executing the default implementation and not the one in MyRPC written by the SDK user.
I feel that I am trying to force Rust to work object oriented, and maybe that is the problem. Should I use a more Rusty approach? I really like our current Golang/Java implementations using this "pattern" since the user only need to write the execute() function and all the underling machinery works, but maybe this won't be an option in Rust.

rust two objects refering each borrow_mut pattern

A similar question I posted earlier is here
Rust can't modify RefCell in Rc, but completely different.
I want to simulate some natural process, so I have a Simulator, and a reactor like a NuclearReactor. The simulator will modify the reactor, and the reactor can reversely influance the simulator by modifying it. One important thing is that the NuclearReactor is wrapped from somewhere else, the solid_function must has a inmutable &self.
So after reading rust book of RefCell, I wrote something like these, It complies, but crashed.
use std::borrow::BorrowMut;
use std::cell::RefCell;
use std::rc::{Rc, Weak};
pub struct Simulator {
nr: NuclearReactor,
data: Vec<f64>,
}
impl Simulator {
pub fn on_nuclear_data(&mut self, x: i64) {
// modify self
}
pub fn run_simulation(&mut self) {
self.nr.write_simulator();
}
}
pub struct NuclearReactor {
simulator: Option<Weak<RefCell<Simulator>>>,
}
impl NuclearReactor {
pub fn solid_function(&self, x: i64) {
/*
this function `&self` is solid, so I have to use a RefCell to wrap Simulator
*/
}
pub fn write_simulator(&self) {
/*
thread 'main' panicked at 'already borrowed: BorrowMutError'
*/
(*self.simulator.as_ref().unwrap().upgrade().unwrap()).borrow_mut().on_nuclear_data(0);
}
}
pub fn main() {
let nr_ = NuclearReactor {
simulator: None
};
let mut sm_ = Rc::new(RefCell::new(Simulator {
nr: nr_,
data: vec![],
}));
(*sm_).borrow_mut().nr.simulator = Some(Rc::downgrade(&sm_));
(*sm_).borrow_mut().run_simulation();
}
Obviously, the runtime check of borrow_mut fails.
Actually the NuclearReactor is my online code, the Simulator is an offline test, so I wanna modify the NuclearReactor at a minimal cost to let it run on the offline environment. That's why I have to keep the function solid_function with an immutable &self. Changing it to a &mut self is and then move to-modifying objects to a seperate function is feasible, but then I have to modify the online code frequently at a high cost. It there anything cool that can solve it ?
Ok, after reading this: http://smallcultfollowing.com/babysteps/blog/2018/11/01/after-nll-interprocedural-conflicts/
I finnaly realized that what I am doing is something like below and rust was helping me avoiding bugs.
let v: Vec<i64> = vec![1,2,3];
for ele in v.iter_mut(){
v.push(1);
}
Thankfully, pushing NuclearReactor's modify to a temp buffer then apply them to Simulator is just enough to solve my problem.
Also, I didn't explain the question clearly (actually I didn't get the point to describe the question until I solved it), so the community can't help me.

How to program shared behaviors in Rust without repeating same code in each module?

For writing a very large program, I see no way to alleviate having to write the same code for each struct that uses a certain shared behaviour.
For example, Dog may "bark":
struct Dog {
is_barking: bool,
....
}
impl Dog {
pub fn bark(self) {
self.is_barking = true;
emit_sound("b");
emit_sound("a");
emit_sound("r");
emit_sound("k");
self.is_barking = false;
}
....
}
And many breeds of this dog may exist:
struct Poodle {
unique_poodle_val: &str
}
impl Poodle {
pub fn unique_behaviour(self) {
self.some_behaviour();
}
}
struct Rottweiler {
unique_rottweiler_val: u32
}
impl Rottweiler{
pub fn unique_behaviour(self) {
self.some_behaviour();
}
}
The issue is that Rust seems incapable of this in my current knowledge, but it needs to be done and I need a workaround for:
Allowing Poodle and Rottweiler to bark using the exact same behavior which the breeds should not need to regard.
Allowing this to be possible without recoding bark() in every breed module, which is programming hell as it leads to repetitious code and every module has to implement bark().
Traits are the inverse and cannot access the struct, so default-trait implements do not work. Rust does not support OOP-like inheritance and nor is it desired here.
Therefore, I ask:
How would it be possible to implement bark() without rewriting bark() in each module, since Poodle and Rottweiler bark exactly the same way after all?
Please provide an example of how to solve this issue in Rust code, idiomatic and slightly hacky solutions are welcome but please state which they are as I am still learning Rust.
Thank you.
Edit: The boolean is not a thread thing, rather it's a example of setting some state before doing something, i.e. emit_sound is within this state. Any code we put into bark() has the same issue. It's the access to the struct variables that is impossible with say, traits.
You've put the finger on something that Rust doesn't do nicely today: concisely add to a struct a behavior based on both internal data and a function.
The most typical way of solving it would probably be to isolate Barking in a struct owned by all dogs (when in doubt, prefer composition over inheritance):
pub struct Barking {
is_barking: bool,
}
impl Barking {
pub fn do_it(&mut self) {
self.is_barking = true; // <- this makes no sense in rust, due to the ownership model
println!("bark");
println!("a");
println!("r");
println!("k");
self.is_barking = false;
}
}
struct Poodle {
unique_poodle_val: String,
barking: Barking,
}
impl Poodle {
pub fn unique_behaviour(self) {
println!("some_behaviour");
}
pub fn bark(&mut self) {
self.barking.do_it();
}
}
struct Rottweiler {
unique_rottweiler_val: u32,
barking: Barking,
}
impl Rottweiler{
pub fn unique_behaviour(self) {
println!("unique behavior");
}
pub fn bark(&mut self) {
// maybe decide to bite instead
self.barking.do_it();
}
}
In some cases it can make sense to define a Barking trait, with a common implementation and declaring some functions to deal with the state:
pub trait Barking {
fn bark(&mut self) {
self.set_barking(true);
println!("bark");
println!("a");
println!("r");
println!("k");
self.set_barking(false);
}
fn set_barking(&mut self, b: bool);
}
struct Poodle {
unique_poodle_val: String,
is_barking: bool,
}
impl Poodle {
pub fn unique_behaviour(self) {
println!("some_behaviour");
}
}
impl Barking for Poodle {
fn set_barking(&mut self, b: bool) {
self.is_barking = b;
}
}
Beware that this half-OOP approach often ends up too much complex and less maintainable (like inheritance in OOP languages).

How to monkeypatch (mock) calls to ncurses crate?

I come from Python where you have monkeypatch in pytest, so I refer to the operation I want to do as monkeypatching, however, I've been told that the actual operation is called mocking more generally.
Anyway, my application uses the ncurses crate, and I need to test some code that calls it. How would I monkeypatch (mock) the calls to crate's functions, methods, and other attributes properly?
For example,
fn get_page(&self, commands: &[String]) -> Vec<String> {
match commands
.chunks(ncurses::LINES() as usize - 3)
.nth(self.page as usize - 1)
{
Some(cmds) => cmds.to_vec(),
None => Vec::new(),
}
}
How would I patch the ncurses::LINES() call?
In python everything is dynamic and patchable, but rust is compiled and concrete. So in your source code you have to explicitly decouple your working code and the library code.
trait NcursesImpl {
// all functions in ncurses that you want to use need to have implementations here.
/// Here is a default implementation that just delegates to ncurses
fn LINES(&self) -> c_int {
ncurses::LINES()
}
}
struct DefaultNCruses;
impl NCursesImpl for DefaultNCurses {
// no functions overridden, everything uses default implementations
}
struct LinesLiarNCurses {
lines: c_int,
}
impl NCursesImpl for LinesLiarNCurses {
/// overrides default implementation for debug purposes
fn LINES(&self) -> c_int {
self.lines
}
}
get_page() has to change slightly to use a NCursesImpl instead of the bare ncurses.
fn get_page(&self, nc: &NCursesImpl, commands: &[String]) -> Vec<String> {
match commands
.chunks(nc.LINES() as usize - 3)
.nth(self.page as usize - 1)
{
Some(cmds) => cmds.to_vec(),
None => Vec::new(),
}
}
I'm not exactly sure where the NCursesImpl object should live. Here I've made it an explicit parameter of the get_page call, but it might actually belong as a member of Self in the struct that has the get_page impl. You might want to store it in a Box<dyn NCursesImpl> so that you don't have type parameters littering your data structures.

How to safely wrap C pointers in rust structs

I am building safe bindings for a C library in Rust and I started facing a weird issue.
I created a struct to own the unsafe pointer to the objects returned by the library and free them safely.
This is what I have:
pub struct VipsImage {
pub(crate) ctx: *mut bindings::VipsImage,
}
impl Drop for VipsImage {
fn drop(&mut self) {
unsafe {
if !self.ctx.is_null() {
bindings::g_object_unref(self.ctx as *mut c_void);
}
}
}
}
This works fine as long as I don't share this between async calls. If I return one of this objects in an async function and use it afterwards it will be corrupted. If I used and free them in a single operation, they work as expected.
How would I implement Send and Sync for a struct like that so I can safely share it between threads?
If someone wants to check the full library code, here's the link

Resources