-
Notifications
You must be signed in to change notification settings - Fork 246
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
Reduce blocking operations in eventloop thread #1342
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. It looks like many of these implementation changes should improve responsiveness during bulk operations. Maybe some of them will even improve throughput for concurrent bulk operations? I didn't try running the benchmarks and comparing against master. Did you try that? Is there a responsiveness benchmark?
Overall the new global state in the implementation is a bit bothersome. I can think of extensive refactorings that would let us avoid that but I'm not sure how realistic those are. Maybe we could try to brainstorm together and see if we can come up with something feasible that avoids it?
@@ -53,9 +53,9 @@ def encode(self, inshares, desired_share_ids=None): | |||
|
|||
for inshare in inshares: | |||
assert len(inshare) == self.share_size, (len(inshare), self.share_size, self.data_size, self.required_shares) | |||
shares = self.encoder.encode(inshares, desired_share_ids) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I understand the code, the Python ZFEC bindings don't release the GIL (which is a good thing, since until very recently the C library initialization was not thread-safe - and now requires an explicit single-threaded initialization step). Were you able to observe any throughput increase with these encode/decode changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mostly just put stuff in threads that the blocking-detector code flagged. I am happy to go and make ZFEC release the GIL as a relevant follow-up.
@@ -767,9 +769,9 @@ def _validate_block(self, results, segnum, reader, server, started): | |||
"block hash tree failure: %s" % e) | |||
|
|||
if self._version == MDMF_VERSION: | |||
blockhash = hashutil.block_hash(salt + block) | |||
blockhash = await defer_to_thread(hashutil.block_hash, salt + block) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shame about that salt + block
, that's presumably a lot of time spent allocating and copying and freeing in the main thread. Possibly a spot for future improvement?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copying memory is actually quite fast typically, but maybe.
Here is my thought on reactor as state: it shouldn't be an attribute or parameter, it should be accessible via a function |
I just looked and |
"In general" trio seems to have better-thought-out async ideas (vs. asyncio) -- although I don't know what it does about the reactor. The asyncio things I have looked at unfortunately have problems similar to many Twisted internal (and third-party) libraries when dealing with the global / implicit reactor ("thread-local context var" still seems global-adjacent to me? but maybe I don't understand ContextVar enough) |
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Looks good to me.
This is likely only a subset, but it's a start.
Fixes https://tahoe-lafs.org/trac/tahoe-lafs/ticket/4068, will probably file follow-up for round 2.