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

[core] Move GCS InternalKV workload to dedicated thread. #47736

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

rynewang
Copy link
Contributor

@rynewang rynewang commented Sep 18, 2024

Most GCS services are on a same asio thread. On really big clusters, e.g. thousands of nodes, event loop queuing time can be an issue. Note we already have task_events and pubsub in dedicated threads and respective event loops and we can dedup code.

Creates a dedicated io context with thread for InternalKV workload, including

  1. InternalKV gRPC service
  2. InMemoryStoreClient callbacks
  3. RedisStoreClient callbacks

Notably gcs_table_storage_ is not on kv_io_service_, because that's used by all other non-KV services and we want it be isolated from the busy kv_io_service_.

This change makes PeriodicalRunner multi-thread. Makes it thread-safe with atomic bool.

Signed-off-by: Ruiyang Wang <rywang014@gmail.com>
@rynewang rynewang requested a review from a team as a code owner September 18, 2024 21:20
Signed-off-by: Ruiyang Wang <rywang014@gmail.com>
@rynewang rynewang force-pushed the dedicated-kv-ioctx branch 2 times, most recently from aadcd14 to c84fd80 Compare September 20, 2024 00:19
@rynewang
Copy link
Contributor Author

Note on the force push:

  1. c84fd80 is the OG commit of internal kv
  2. aadcd14 is a PR + GcsNodeManager to its dedicated thread. This did not work and causes segfault since now the thread + the main thread both RW the GcsNodeManager internal maps.
  3. Now, reverting to c84fd80 and merge master.

@rynewang rynewang added the go add ONLY when ready to merge, run all tests label Sep 23, 2024
Signed-off-by: Ruiyang Wang <rywang014@gmail.com>
Signed-off-by: Ruiyang Wang <rywang014@gmail.com>
Signed-off-by: Ruiyang Wang <rywang014@gmail.com>
@rynewang
Copy link
Contributor Author

Note: TSAN captured a new data race: GetAllJobInfo sends RPCs to workers (main thread) and KVMultiGet (the new ioctx thread). Both modifies a counter that implements a "gather all these tasks and then run callback" logic. I don't want a new mutex just for this; so I used atomics.

So now, both threads access to a same atomic<size_t>. They perform atomic fetch_add to increment the counter and use the atomic readout value to determine if the callback can be run. This also simplifies code from an int + a bool to a single size_t.

Signed-off-by: Ruiyang Wang <rywang014@gmail.com>
Signed-off-by: Ruiyang Wang <rywang014@gmail.com>
Comment on lines 844 to 854
RAY_LOG(INFO) << "main_service_ Event stats:\n\n"
<< main_service_.stats().StatsString() << "\n\n";
RAY_LOG(INFO) << "pubsub_io_context_ Event stats:\n\n"
<< pubsub_io_context_.GetIoService().stats().StatsString() << "\n\n";
RAY_LOG(INFO) << "kv_io_context_ Event stats:\n\n"
<< kv_io_context_.GetIoService().stats().StatsString() << "\n\n";
RAY_LOG(INFO) << "task_io_context_ Event stats:\n\n"
<< task_io_context_.GetIoService().stats().StatsString() << "\n\n";
RAY_LOG(INFO) << "ray_syncer_io_context_ Event stats:\n\n"
<< ray_syncer_io_context_.GetIoService().stats().StatsString()
<< "\n\n";
Copy link
Contributor

Choose a reason for hiding this comment

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

This is user-facing, let's make this user-friendly -- instead of using field name describe what they are

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 placed it this way for ease of searching logs - I don't think Ray users (other than Core developers) will ever need to read this...

src/ray/gcs/gcs_server/gcs_job_manager.cc Outdated Show resolved Hide resolved
Signed-off-by: Ruiyang Wang <rywang014@gmail.com>
Signed-off-by: Ruiyang Wang <rywang014@gmail.com>
Copy link
Collaborator

@jjyao jjyao left a comment

Choose a reason for hiding this comment

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

There is refactoring in this PR. Can we have the refactoring in its own PR first?

* The constructor takes a thread name and starts the thread.
* The destructor stops the io_service and joins the thread.
*/
class InstrumentedIoContextWithThread {
Copy link
Collaborator

Choose a reason for hiding this comment

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

should be IO instead of Io? lol

Copy link
Collaborator

@jjyao jjyao left a comment

Choose a reason for hiding this comment

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

There is refactoring in this PR. Can we have the refactoring in its own PR first?

Signed-off-by: Ruiyang Wang <rywang014@gmail.com>
rynewang added a commit that referenced this pull request Sep 26, 2024
Every time GetInternalConfig reads from table_storage, but it's never
mutated. Moves to internal kv as a simple in-mem get (no more read from
redis). This itself should slightly update performance. But with #47736
it should improve start up latency a lot in thousand-node clusters. In
theory we can remove it all for good, instead just put it as an
InternalKV entry. but let's do things step by step.

Signed-off-by: Ruiyang Wang <rywang014@gmail.com>
Signed-off-by: Ruiyang Wang <56065503+rynewang@users.noreply.github.com>
Signed-off-by: Ruiyang Wang <rywang014@gmail.com>
Signed-off-by: Ruiyang Wang <rywang014@gmail.com>
Signed-off-by: Ruiyang Wang <rywang014@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
go add ONLY when ready to merge, run all tests
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants