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

Rename worker threads in blocking regions #3012

Merged
merged 1 commit into from
Jun 27, 2022

Conversation

aeons
Copy link
Member

@aeons aeons commented Jun 1, 2022

This adds a new parameter to the WorkStealingThreadPool constructor, but it looks like the constructor is private to the project.

Closes #3010

"rename itself when entering and exiting blocking region" in real {
for {
computeThreadName <- getThreadName
blockerThreadName <- blocking { getThreadName }
Copy link
Member Author

Choose a reason for hiding this comment

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

Is it correctly understood that this works the same as using IO.blocking?

Copy link
Member

@armanbilge armanbilge Jun 1, 2022

Choose a reason for hiding this comment

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

I'm not sure, so Vasil will have to comment. But my understanding was the IO.blocking calls can be shifted to an existing blocking thread if available. However because blocking { } is synchronous, it forces the current thread to become a blocking thread. So possibly not the same.

Also the semantics here seem a bit strange, maybe you actually want IO(blocking(Thread.currentThread().getName()))?

Copy link
Member

Choose a reason for hiding this comment

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

I would not test scala.concurrent.blocking and I would advise against using it to wrap effects.

The more correct usage is to wrap effectful code directly, like Arman suggested.

Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure, so Vasil will have to comment. But my understanding was the IO.blocking calls can be shifted to an existing blocking thread if available. However because blocking { } is synchronous, it forces the current thread to become a blocking thread. So possibly not the same.

IO.blocking calls are either:

  1. Rewritten as IO(scala.concurrent.blocking(thunk)) and then executed in place, by making the current compute thread become a blocking thread and replacing it with a cached/new thread.
  2. Shifted completely to the blocking pool and then shifted back to the compute pool.

Cached threads that blocked at one time can be used as replacements for compute threads again, but not directly as blocking threads.

Copy link
Member

Choose a reason for hiding this comment

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

Cached threads that blocked at one time can be used as replacements for compute threads again, but not directly as blocking threads.

Oh interesting, at the risk of going on a tangent why is that?

Copy link
Member Author

Choose a reason for hiding this comment

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

Changing it to IO.blocking

Copy link
Member

Choose a reason for hiding this comment

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

Oh interesting, at the risk of going on a tangent why is that?

If you shift a fiber to a dedicated blocking thread (regardless of whether it's cached or spawned just now) you incur 2 context switches (one by switching to the blocking thread and one by switching back to the compute pool). Runnin the blocking code in place and replacing the thread only incurs 1 context switch, when you go back to the compute pool. This is demonstrably quicker on benchmarks, something CE was criticized for (inefficiency of blocking code execution) now it benches the same as the best of them.

Copy link
Member

Choose a reason for hiding this comment

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

"rename itself when entering and exiting blocking region" in real {
for {
computeThreadName <- getThreadName
blockerThreadName <- blocking { getThreadName }
Copy link
Member

@armanbilge armanbilge Jun 1, 2022

Choose a reason for hiding this comment

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

I'm not sure, so Vasil will have to comment. But my understanding was the IO.blocking calls can be shifted to an existing blocking thread if available. However because blocking { } is synchronous, it forces the current thread to become a blocking thread. So possibly not the same.

Also the semantics here seem a bit strange, maybe you actually want IO(blocking(Thread.currentThread().getName()))?

Comment on lines 31 to 32
_ <- IO.cede
resetComputeThreadName <- getThreadName
Copy link
Member

Choose a reason for hiding this comment

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

From my understanding, this doesn't check if the thread name is reset. All it's checking is that the fiber is now running on a compute thread, which is not the same thing.

It seems to me all of your assertions should check that the underlying thread is the same (by reference equality) so that we are in fact seeing name changes (and not simply thread jumps).

Copy link
Member Author

Choose a reason for hiding this comment

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

You are right. My first test that didn't work, without the cede, had the same thread id for all three fibers. Now the first two are the same and correctly changes name, but the last one is on a different thread.

Copy link
Member Author

Choose a reason for hiding this comment

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

I removed my debug println (😳) and updated the test.

What it does now is

  • create a runtime with a single thread threadpool,
  • check that the compute thread is correctly renamed when entering a blocking region,
  • then force two threads to become blocking,
  • thus forcing the previously blocking thread to be readded to the compute pool
  • and verify that the thread has been renamed again

It works, but feels iffy.

@armanbilge
Copy link
Member

Oh also, this PR can probably be targeted at 3.3.x, so we can release it sooner :)

@aeons aeons changed the base branch from series/3.x to series/3.3.x June 1, 2022 16:56
@aeons aeons changed the base branch from series/3.3.x to series/3.x June 1, 2022 17:02
@aeons
Copy link
Member Author

aeons commented Jun 2, 2022

I guess that involves rebasing on series/3.3.x and changing the target branch here, right?

Just confirming before I force push.

@aeons
Copy link
Member Author

aeons commented Jun 7, 2022

/poke @armanbilge

@vasilmkd
Copy link
Member

vasilmkd commented Jun 7, 2022

I would like to review this PR too. Please give me a few days. Sorry for the delay.

@armanbilge
Copy link
Member

Sorry, missed your message! Yes, you should rebase and force push.

@aeons aeons changed the base branch from series/3.x to series/3.3.x June 9, 2022 08:48
@aeons
Copy link
Member Author

aeons commented Jun 9, 2022

It should be ready now, targeting series/3.3.x.

@djspiewak
Copy link
Member

Holding the merge on this until @vasilmkd approves.

@djspiewak
Copy link
Member

@vasilmkd Any availability to review within the next day or so? I'd like to get this merged. All good if you're not able to get to it.

@vasilmkd
Copy link
Member

I will review it tomorrow, I don't have a computer at the moment. I'm sorry for the delay. 😄

@aeons aeons requested a review from vasilmkd June 23, 2022 08:06
Copy link
Member

@vasilmkd vasilmkd left a comment

Choose a reason for hiding this comment

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

Great work, thanks for chasing this down, and sorry for the delay.

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.

Change thread name when it becomes a "blocker"
4 participants