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

Redo TaskFaker's internal queue #8348

Merged
merged 5 commits into from
Apr 11, 2024
Merged

Redo TaskFaker's internal queue #8348

merged 5 commits into from
Apr 11, 2024

Conversation

swankjesse
Copy link
Member

Previously this used locks to stop threads from executing. Now it uses a custom 'yield' function to accomplish a similar purpose. The main benefit of the new approach is we're no longer subject to unspecified lock release order - we maintain our own queue and get true deterministic order of execution.

Previously this used locks to stop threads from executing. Now
it uses a custom 'yield' function to accomplish a similar purpose.
The main benefit of the new approach is we're no longer subject
to unspecified lock release order - we maintain our own queue
and get true deterministic order of execution.
@swankjesse swankjesse marked this pull request as ready for review April 9, 2024 03:49
Copy link
Collaborator

@yschimke yschimke left a comment

Choose a reason for hiding this comment

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

This is a tough review. But tests look good to cover risk. And nice wins.

* @param resumeEagerly true to prioritize the current task over other queued tasks.
* @param yieldUntilExhausted true to keep yielding until there's no other runnable tasks.
*/
private tailrec fun yieldUntil(
Copy link
Collaborator

Choose a reason for hiding this comment

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

Tailrec, I'm impressed.

"plan 0 cancel",
"plan 0 TCP connect canceled",
Copy link
Collaborator

Choose a reason for hiding this comment

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

Woot!

@@ -78,7 +79,6 @@ class RealWebSocketTest {
@Test
fun close() {
client.webSocket!!.close(1000, "Hello!")
taskFaker.runTasks()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nice simplification

Copy link
Collaborator

@ean5533 ean5533 left a comment

Choose a reason for hiding this comment

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

This was a tough change to review. There's several different concurrency mechanisms here that have to be coordinated just right. Even now I feel like I've only internalized about 2/3 of how it all works. Which (along with passing tests) is enough for me to feel good approving it, but I don't envy any non-Jesses who want to touch this code in the future.

By the way, you also could (should?) uncomment the ConnectionPoolTest.connectionPreWarming() as part of this PR.

private var tasksRunningCount = 0
private val tasksExecutor =
Executors.newCachedThreadPool(
object : ThreadFactory {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: should we throw this into a little utility class somewhere? e.g.

class NamedThreadFactory(val prefix): ThreadFactory {
  private var nextId = 1

  override fun newThread(runnable: Runnable) = Thread(runnable, "$prefix-${nextId++}")
}

Copy link
Member Author

Choose a reason for hiding this comment

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

Good idea. Coming up in follow-up.

Comment on lines 249 to 250
resumeEagerly: Boolean = false,
yieldUntilExhausted: Boolean = false,
Copy link
Collaborator

Choose a reason for hiding this comment

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

It feels like these two parameters should be mutually exclusive; it doesn't make sense to use them both. If a caller does set both to true then I believe yieldUntilExhausted will have no effect.

Maybe replace these two params with a single enum parameter?

enum class YieldStrategy {
  Eager,          // Prioritizes this task
  Lazy,           // Prioritizes all other currently queued tasks
  UntilExhausted, // Prioritizes all other queued tasks, including new tasks enqueued while waiting
}

(wordsmith as needed)

Copy link
Member Author

Choose a reason for hiding this comment

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

Wordsmitthed! I turned your great comments into the member names.

  private enum class ResumePriority {
    /** Resumes as soon as the condition is satisfied. */
    BeforeOtherTasks,

    /** Resumes after the already-enqueued tasks. */
    AfterEnqueuedTasks,

    /** Resumes after all other tasks, including tasks enqueued while yielding. */
    AfterOtherTasks,
  }

stall()
taskRunner.assertThreadDoesntHoldLock()
taskRunner.lock.withLock {
yieldUntil()
Copy link
Collaborator

Choose a reason for hiding this comment

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

This method call is confusing at first glance until you go read all the default param values.

But I don't have any suggestions to make it better 🤷

Copy link
Member Author

Choose a reason for hiding this comment

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

Agreed!

@swankjesse swankjesse merged commit 27670f9 into master Apr 11, 2024
20 checks passed
@swankjesse swankjesse deleted the jwilson.0407.taskfaker branch April 11, 2024 01:59
ean5533 added a commit that referenced this pull request Apr 11, 2024
1. The first test just needed to be uncommented now that #8348 is merged
2. A second test was added to exercise http2-specific functionality
ean5533 added a commit that referenced this pull request Apr 11, 2024
1. The first test just needed to be uncommented now that #8348 is merged
2. A second test was added to exercise http2-specific functionality
ean5533 added a commit that referenced this pull request Apr 12, 2024
1. The first test just needed to be uncommented now that #8348 is merged
2. A second test was added to exercise http2-specific functionality
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.

None yet

3 participants