Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lazy_static rhai Engine #112

Closed
wants to merge 4 commits into from
Closed

lazy_static rhai Engine #112

wants to merge 4 commits into from

Conversation

DevinR528
Copy link
Contributor

@DevinR528 DevinR528 commented Apr 13, 2020

Relates to #109

Add block_on which tests a future with no runtime overhead.

use lazy_static to only create one Engine per Enforcer not on every enforece() call.

@codecov
Copy link

codecov bot commented Apr 13, 2020

Codecov Report

Merging #112 into master will decrease coverage by 0.02%.
The diff coverage is 66.66%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #112      +/-   ##
==========================================
- Coverage   86.97%   86.95%   -0.03%     
==========================================
  Files          19       19              
  Lines        2834     2836       +2     
==========================================
+ Hits         2465     2466       +1     
- Misses        369      370       +1     
Impacted Files Coverage Δ
src/enforcer.rs 90.84% <66.66%> (-0.19%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 71f93f3...eed670f. Read the comment docs.

src/enforcer.rs Outdated
if !self.enabled {
return Ok(true);
}

let mut engine = Engine::new();
let mut engine = ENGINE.write().unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The original version of enforce is lock-free, will this change makes enforce can't handle concurrent request because every request have to wait for the write lock.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if it matters, I can't get it to panic even using RwLock::try_write in either an async spawned context or on a std thread. The only way to pass the Enforcer to a thread or an async_std::spawn is to wrap it in some type of sync control. I'm pushing another commit mostly to show the test I wrote for this. If you can think of any other ways to pass this into concurrent execution it'd be great to add them to the test.

This also reminds me I was wondering about using async_std::sync::RwLock/Mutex instead of std's RwLock/Mutex. There is a discussion about this sort of here

Copy link
Member

@GopherJ GopherJ Apr 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we do have only one enforcer, it's ok to use lazy_static, but I would say if the users created multiple enforcers. It will cause problems because basically they will share the same Engine and the more enforcers we have, the worser result we get. => This is also why I removed lazy_static event emitter from the code

@xcaptain @DevinR528 I think inline engine, scope will improve bench about 15%, but yes I didn't succeed to implement it yesterday due to lifetime issue.

May try again in the future

@DevinR528 You are right we shouldn't use std::sync::RwLock to wrap a type which implemented many async functions. Because .await requires Send and std::sync::RwLockGuard is not send. That causes also difficutiles when I try to implement a clonable SyncedEnforcer, which is basically Arc<RwLock<Enforcer/CachedEnforcer>>. This maybe out of topic

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of just one Engine could you have a lazy_static Arc<Mutex<Vec<Engine>>> and every time Enforcer::new is called you push a new Engine into the vec and assign an index for that Enforcer instance? I'm going to make a somewhat educated guess that the lifetime issues may be insurmountable 😢, basically the lifetime of the &str's passed to Scope::push_constant become the lifetime of the &mut self borrow for Enforcer::enforce and there doesn't seem to be a way to say a lifetime that is smaller than the lifetime of the Enforcer struct which is what you need.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@DevinR528
Arc<Mutex<Vec<Engine>>> still require write access, it means when one enforcer is enforcing, there won't be any other enforcer can acquire a engine.

I believe rhai::Engine 's lifetime is to for the registered functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh right the vec won't work at all. I had one more idea creating a lockless AtomicPtr struct that has a flag for when the Engine is in use and either starts we a few Engines or adds to a vec as needed.

@GopherJ
Copy link
Member

GopherJ commented Apr 16, 2020

closed as solved in #117 , we dont need to share scope because it took only 5ns to create

@GopherJ GopherJ closed this Apr 16, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants