Skip to content

Commit ca6461c

Browse files
committed
Add proof-of-concept QoS implementation
1 parent bb78059 commit ca6461c

File tree

14 files changed

+254
-23
lines changed

14 files changed

+254
-23
lines changed

Cargo.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/flycheck/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ cargo_metadata = "0.15.0"
1818
rustc-hash = "1.1.0"
1919
serde_json.workspace = true
2020
serde.workspace = true
21-
jod-thread = "0.1.2"
2221
command-group = "2.0.1"
2322

2423
# local deps

crates/flycheck/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ impl fmt::Display for FlycheckConfig {
7777
pub struct FlycheckHandle {
7878
// XXX: drop order is significant
7979
sender: Sender<StateChange>,
80-
_thread: jod_thread::JoinHandle,
80+
_thread: stdx::thread::JoinHandle,
8181
id: usize,
8282
}
8383

@@ -90,7 +90,7 @@ impl FlycheckHandle {
9090
) -> FlycheckHandle {
9191
let actor = FlycheckActor::new(id, sender, config, workspace_root);
9292
let (sender, receiver) = unbounded::<StateChange>();
93-
let thread = jod_thread::Builder::new()
93+
let thread = stdx::thread::Builder::new(stdx::thread::QoSClass::Utility)
9494
.name("Flycheck".to_owned())
9595
.spawn(move || actor.run(receiver))
9696
.expect("failed to spawn thread");
@@ -395,7 +395,7 @@ struct CargoHandle {
395395
/// The handle to the actual cargo process. As we cannot cancel directly from with
396396
/// a read syscall dropping and therefore terminating the process is our best option.
397397
child: JodGroupChild,
398-
thread: jod_thread::JoinHandle<io::Result<(bool, String)>>,
398+
thread: stdx::thread::JoinHandle<io::Result<(bool, String)>>,
399399
receiver: Receiver<CargoMessage>,
400400
}
401401

@@ -409,7 +409,7 @@ impl CargoHandle {
409409

410410
let (sender, receiver) = unbounded();
411411
let actor = CargoActor::new(sender, stdout, stderr);
412-
let thread = jod_thread::Builder::new()
412+
let thread = stdx::thread::Builder::new(stdx::thread::QoSClass::Utility)
413413
.name("CargoHandle".to_owned())
414414
.spawn(move || actor.run())
415415
.expect("failed to spawn thread");

crates/ide/src/prime_caches.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ pub(crate) fn parallel_prime_caches(
8080
for _ in 0..num_worker_threads {
8181
let worker = prime_caches_worker.clone();
8282
let db = db.snapshot();
83-
std::thread::spawn(move || Cancelled::catch(|| worker(db)));
83+
84+
stdx::thread::Builder::new(stdx::thread::QoSClass::Utility)
85+
.allow_leak(true)
86+
.spawn(move || Cancelled::catch(|| worker(db)))
87+
.expect("failed to spawn thread");
8488
}
8589

8690
(work_sender, progress_receiver)

crates/proc-macro-srv/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ object = { version = "0.30.2", default-features = false, features = [
2222
libloading = "0.7.3"
2323
memmap2 = "0.5.4"
2424

25+
stdx.workspace = true
2526
tt.workspace = true
2627
mbe.workspace = true
2728
paths.workspace = true

crates/rust-analyzer/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ jemallocator = { version = "0.5.0", package = "tikv-jemallocator", optional = tr
8686

8787
[dev-dependencies]
8888
expect-test = "1.4.0"
89-
jod-thread = "0.1.2"
9089
xshell = "0.2.2"
9190

9291
test-utils.workspace = true

crates/rust-analyzer/src/bin/main.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ fn try_main(flags: flags::RustAnalyzer) -> Result<()> {
7878
println!("rust-analyzer {}", rust_analyzer::version());
7979
return Ok(());
8080
}
81-
with_extra_thread("LspServer", run_server)?;
81+
with_extra_thread("LspServer", stdx::thread::QoSClass::Utility, run_server)?;
8282
}
8383
flags::RustAnalyzerCmd::Parse(cmd) => cmd.run()?,
8484
flags::RustAnalyzerCmd::Symbols(cmd) => cmd.run()?,
@@ -136,14 +136,17 @@ const STACK_SIZE: usize = 1024 * 1024 * 8;
136136
/// space.
137137
fn with_extra_thread(
138138
thread_name: impl Into<String>,
139+
qos_class: stdx::thread::QoSClass,
139140
f: impl FnOnce() -> Result<()> + Send + 'static,
140141
) -> Result<()> {
141-
let handle =
142-
std::thread::Builder::new().name(thread_name.into()).stack_size(STACK_SIZE).spawn(f)?;
143-
match handle.join() {
144-
Ok(res) => res,
145-
Err(panic) => std::panic::resume_unwind(panic),
146-
}
142+
let handle = stdx::thread::Builder::new(qos_class)
143+
.name(thread_name.into())
144+
.stack_size(STACK_SIZE)
145+
.spawn(f)?;
146+
147+
handle.join()?;
148+
149+
Ok(())
147150
}
148151

149152
fn run_server() -> Result<()> {

crates/rust-analyzer/src/task_pool.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! A thin wrapper around `ThreadPool` to make sure that we join all things
22
//! properly.
3+
use std::sync::{Arc, Barrier};
4+
35
use crossbeam_channel::Sender;
46

57
pub(crate) struct TaskPool<T> {
@@ -16,6 +18,18 @@ impl<T> TaskPool<T> {
1618
.thread_stack_size(STACK_SIZE)
1719
.num_threads(threads)
1820
.build();
21+
22+
// Set QoS of all threads in threadpool.
23+
let barrier = Arc::new(Barrier::new(threads + 1));
24+
for _ in 0..threads {
25+
let barrier = barrier.clone();
26+
inner.execute(move || {
27+
stdx::thread::set_current_thread_qos_class(stdx::thread::QoSClass::Utility);
28+
barrier.wait();
29+
});
30+
}
31+
barrier.wait();
32+
1933
TaskPool { sender, inner }
2034
}
2135

@@ -26,7 +40,16 @@ impl<T> TaskPool<T> {
2640
{
2741
self.inner.execute({
2842
let sender = self.sender.clone();
29-
move || sender.send(task()).unwrap()
43+
move || {
44+
if stdx::thread::IS_QOS_AVAILABLE {
45+
debug_assert_eq!(
46+
stdx::thread::get_current_thread_qos_class(),
47+
Some(stdx::thread::QoSClass::Utility)
48+
);
49+
}
50+
51+
sender.send(task()).unwrap()
52+
}
3053
})
3154
}
3255

crates/rust-analyzer/tests/slow-tests/support.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ pub(crate) fn project(fixture: &str) -> Server {
155155
pub(crate) struct Server {
156156
req_id: Cell<i32>,
157157
messages: RefCell<Vec<Message>>,
158-
_thread: jod_thread::JoinHandle<()>,
158+
_thread: stdx::thread::JoinHandle,
159159
client: Connection,
160160
/// XXX: remove the tempdir last
161161
dir: TestDir,
@@ -165,7 +165,7 @@ impl Server {
165165
fn new(dir: TestDir, config: Config) -> Server {
166166
let (connection, client) = Connection::memory();
167167

168-
let _thread = jod_thread::Builder::new()
168+
let _thread = stdx::thread::Builder::new(stdx::thread::QoSClass::Utility)
169169
.name("test server".to_string())
170170
.spawn(move || main_loop(config, connection).unwrap())
171171
.expect("failed to spawn a thread");

crates/stdx/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ doctest = false
1515
libc = "0.2.135"
1616
backtrace = { version = "0.3.65", optional = true }
1717
always-assert = { version = "0.1.2", features = ["log"] }
18+
jod-thread = "0.1.2"
1819
# Think twice before adding anything here
1920

2021
[target.'cfg(windows)'.dependencies]

0 commit comments

Comments
 (0)