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

implement high contention allocator #122

Merged
merged 7 commits into from
Jun 4, 2019

Conversation

pH14
Copy link
Collaborator

@pH14 pH14 commented May 25, 2019

Hey folks, I took a stab at writing the HCA (#44) for the DirectoryLayer and was looking for some early feedback on it. I've never written Rust before, so I didn't want to go too deep into writing up docs if there's still a lot to iterate on code-wise 😅

The implementation is pretty much just porting over the Go bindings. From a brief reading, it looks like more of the DirectoryLayer needs to be implemented before we can use the bindingtester to verify correctness.

@bluejekyll @yjh0502

subspace: &Subspace,
) -> Result<Subspace, Error> {
loop {
let range_option = RangeOptionBuilder::from(self.counters.range())
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

one question I had: this RangeOption gets remade a bunch of times, what's a good way to dedupe that work? Should it be set as a const and update get_ranges to work over references?

Copy link
Collaborator

@bluejekyll bluejekyll May 25, 2019

Choose a reason for hiding this comment

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

Generally speaking, it might be easier to create a RangeOptionRef type then trying to make the existing one generic over both owned and reference types. I’ll need to refresh my memory though and review the code. I’ll try and do that ASAP.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Reviewing the code, this would be a good change, to make a RangeOptionRef that could be constructed directly from the two vecs from get_ranges(). I'm not sure why that is returning Vecs. This might end up being a rather large and deep change though.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

One additional tricky piece about this method I later learned: RangeOptionBuilder::from(subspace.range()) compiles, but since range() returns (Vec<u8>, Vec<u8>), and because we have tuple definitions for pairs + Vec<u8> Elements, it actually gets interpreted as a Tuple. This then produces a Range that spans [(begin, end, 0x00), (begin, end, 0xFF)).

Maybe we could add a key/range-convertible trait that both tuples / subspaces implement that returns (KeySelector, KeySelector)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

For either case, I might hold off on these changes to keep this PR scoped down

Copy link
Collaborator

Choose a reason for hiding this comment

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

Sorry for the late reply. Yes, I'm sure this could be cleaned up quite a bit.

Copy link
Collaborator

@bluejekyll bluejekyll left a comment

Choose a reason for hiding this comment

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

It would be great to add a test for this feature. See: https://github.com/bluejekyll/foundationdb-rs/tree/master/foundationdb/tests

Otherwise, there are a few questions and one thing that could be cleaned up. I also recommend running cargo clippy, it might offer some hints about ways to improve the code.

if start < 65535 {
return 1024;
}
return 8192;
Copy link
Collaborator

Choose a reason for hiding this comment

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

This block could be a little cleaner in Rust as:

match start {
    _ if start < 255 => 64,
    _ if start < 65535 => 1024,
    _ => 8192,
}

subspace: &Subspace,
) -> Result<Subspace, Error> {
loop {
let range_option = RangeOptionBuilder::from(self.counters.range())
Copy link
Collaborator

Choose a reason for hiding this comment

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

Reviewing the code, this would be a good change, to make a RangeOptionRef that could be constructed directly from the two vecs from get_ranges(). I'm not sure why that is returning Vecs. This might end up being a rather large and deep change though.

let kvs = range_result.key_values();

for kv in kvs.as_ref() {
if let Element::I64(counter) = self.counters.unpack(kv.key()).expect("unable to unpack counter key") {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this be an error rather than a panic?

const ONE_BYTES: &[u8] = &[0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];

/// High Contention Allocator
///
Copy link
Collaborator

Choose a reason for hiding this comment

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

It would be great to have a bit more documentation (perhaps from the FoundationDB docs themselves) that describes this feature.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yes, will get to this next 👍

use tuple::Element;

lazy_static! {
static ref LOCK: Mutex<i32> = Mutex::new(0);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this lock truly global? or should it be limited to each instance of an HCA?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

still not sure about this one. I'll dig into the other bindings some more

@pH14
Copy link
Collaborator Author

pH14 commented May 31, 2019

Added some tests and got it working correctly. I'll take another pass at docs + looking into the mutex behavior in the next few days. Thank you for the comments!

@pH14
Copy link
Collaborator Author

pH14 commented Jun 1, 2019

Added some docs, and moved the mutex out of global state and into the HCA. From my understanding, the mutex is to prevent an individual transaction from racing if it has concurrent calls into the HCA. The Java + Go bindings use a global mutex, the Python + Ruby bindings create a transaction-local variable to lock on, and the Flow bindings don't lock at all. All this to say, an HCA-mutex ought to work fine here.

@bluejekyll
Copy link
Collaborator

This all looks good up to this point. We maybe want to revisit the design of the function for the windows creation logic in the future. I think that could probably be more elegantly modeled as a set of state machines, but not necessary at this point.

It looks like some of the tests are failing. I’m happy to merge once those are passing unless @yjh0502 has any concerns.

@pH14
Copy link
Collaborator Author

pH14 commented Jun 2, 2019

Still getting used to the idea of builds failing from doc formatting! Fixed the comments.

@bluejekyll
Copy link
Collaborator

Just got a quick sec. This looks good. Thanks for the PR!

Any interest in being a maintainer on the project? It's not at the top of my mind at the moment. It could be moved to a more neutral organization if that's desirable. @yjh0502 any concerns?

@bluejekyll bluejekyll merged commit 731ed94 into Clikengo:master Jun 4, 2019
@pH14 pH14 deleted the add-high-contention-allocator branch June 5, 2019 12:41
@pH14
Copy link
Collaborator Author

pH14 commented Jun 6, 2019

@bluejekyll I could try 😄 I'm still learning rust, but I have a decent grasp of the FDB API

@pH14 pH14 mentioned this pull request Jul 10, 2019
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.

2 participants