Skip to content

Commit ef0b256

Browse files
authored
core: Allow caller to decide whether or not IRQ cores should be reserved (#2913)
1 parent c871610 commit ef0b256

File tree

1 file changed

+18
-15
lines changed

1 file changed

+18
-15
lines changed

crates/core/src/startup.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use core_affinity::CoreId;
21
use crossbeam_queue::ArrayQueue;
32
use itertools::Itertools;
43
use spacetimedb_paths::server::{ConfigToml, LogsDir};
@@ -16,6 +15,8 @@ use tracing_subscriber::{reload, EnvFilter};
1615
use crate::config::{ConfigFile, LogConfig};
1716
use crate::util::jobs::JobCores;
1817

18+
pub use core_affinity::CoreId;
19+
1920
pub struct TracingOptions {
2021
pub config: LogConfig,
2122
/// Whether or not to periodically reload the log config in the background.
@@ -196,6 +197,13 @@ pub struct CoreReservations {
196197
///
197198
/// Default: 1/8
198199
pub rayon: f64,
200+
/// Cores to reserve for IRQ handling.
201+
///
202+
/// This will be the first `n` [`CoreId`]s in the list.
203+
/// Only make use of this if you're configuring the machine for IRQ pinning!
204+
///
205+
/// Default: 2
206+
pub irq: usize,
199207
/// Extra reserved cores.
200208
///
201209
/// If greater than zero, this many cores will be reserved _before_
@@ -211,6 +219,7 @@ impl Default for CoreReservations {
211219
databases: 1.0 / 8.0,
212220
tokio_workers: 4.0 / 8.0,
213221
rayon: 1.0 / 8.0,
222+
irq: 2,
214223
reserved: 0,
215224
}
216225
}
@@ -221,13 +230,15 @@ impl CoreReservations {
221230
///
222231
/// Returns the allocated cores in the order:
223232
///
233+
/// - irq
224234
/// - reserved
225235
/// - databases
226236
/// - tokio_workers
227237
/// - rayon
228238
///
229239
/// Left public for testing and debugging purposes.
230-
pub fn apply(&self, cores: &mut Vec<CoreId>) -> [Vec<CoreId>; 4] {
240+
pub fn apply(&self, cores: &mut Vec<CoreId>) -> [Vec<CoreId>; 5] {
241+
let irq = cores.drain(..self.irq).collect_vec();
231242
let reserved = cores.drain(..self.reserved).collect_vec();
232243

233244
let total = cores.len() as f64;
@@ -240,7 +251,7 @@ impl CoreReservations {
240251
let tokio_workers = claim(cores, frac(self.tokio_workers)).collect_vec();
241252
let rayon = claim(cores, frac(self.rayon)).collect_vec();
242253

243-
[reserved, databases, tokio_workers, rayon]
254+
[irq, reserved, databases, tokio_workers, rayon]
244255
}
245256
}
246257

@@ -273,7 +284,7 @@ impl Cores {
273284
fn get(reservations: CoreReservations) -> Option<Self> {
274285
let mut cores = Self::get_core_ids()?;
275286

276-
let [reserved, databases, tokio_workers, rayon] = reservations.apply(&mut cores);
287+
let [_irq, reserved, databases, tokio_workers, rayon] = reservations.apply(&mut cores);
277288

278289
let reserved = (!reserved.is_empty()).then(|| reserved.into());
279290
let databases = databases.into_iter().collect::<JobCores>();
@@ -306,20 +317,12 @@ impl Cores {
306317

307318
/// Get the cores of the local host, as reported by the operating system.
308319
///
309-
/// Cores 0 and 1 are not included in the returned vec, as we reserve them
310-
/// for the operating system.
311-
///
312-
/// Returns `None` if `num_cpus - 2` is less than 8.
320+
/// Returns `None` if `num_cpus` is less than 8.
313321
/// If `Some` is returned, the `Vec` is non-empty.
314322
pub fn get_core_ids() -> Option<Vec<CoreId>> {
315323
let cores = core_affinity::get_core_ids()
316324
.filter(|cores| cores.len() >= 10)?
317325
.into_iter()
318-
// We reserve the first two cores for the OS.
319-
// This allows us to pin interrupt handlers (IRQs) to these cores,
320-
// particularly those for incoming network traffic,
321-
// preventing them from preempting the main reducer threads.
322-
.filter(|core_id| core_id.id > 1)
323326
.collect_vec();
324327

325328
(!cores.is_empty()).then_some(cores)
@@ -328,14 +331,14 @@ impl Cores {
328331

329332
#[derive(Default)]
330333
pub struct TokioCores {
331-
workers: Option<Vec<CoreId>>,
334+
pub workers: Option<Vec<CoreId>>,
332335
// For blocking threads, we don't want to limit them to a specific number
333336
// and pin them to their own cores - they're supposed to run concurrently
334337
// with each other. However, `core_affinity` doesn't support affinity masks,
335338
// so we just use the Linux-specific API, since this is only a slight boost
336339
// and we don't care enough about performance on other platforms.
337340
#[cfg(target_os = "linux")]
338-
blocking: Option<nix::sched::CpuSet>,
341+
pub blocking: Option<nix::sched::CpuSet>,
339342
}
340343

341344
impl TokioCores {

0 commit comments

Comments
 (0)