bevy_core/
task_pool_options.rs1use bevy_tasks::{AsyncComputeTaskPool, ComputeTaskPool, IoTaskPool, TaskPoolBuilder};
2use bevy_utils::tracing::trace;
3
4#[derive(Clone, Debug)]
7pub struct TaskPoolThreadAssignmentPolicy {
8 pub min_threads: usize,
10 pub max_threads: usize,
12 pub percent: f32,
15}
16
17impl TaskPoolThreadAssignmentPolicy {
18 fn get_number_of_threads(&self, remaining_threads: usize, total_threads: usize) -> usize {
20 assert!(self.percent >= 0.0);
21 let mut desired = (total_threads as f32 * self.percent).round() as usize;
22
23 desired = desired.min(remaining_threads);
25
26 desired.clamp(self.min_threads, self.max_threads)
30 }
31}
32
33#[derive(Clone, Debug)]
36pub struct TaskPoolOptions {
37 pub min_total_threads: usize,
40 pub max_total_threads: usize,
43
44 pub io: TaskPoolThreadAssignmentPolicy,
46 pub async_compute: TaskPoolThreadAssignmentPolicy,
48 pub compute: TaskPoolThreadAssignmentPolicy,
50}
51
52impl Default for TaskPoolOptions {
53 fn default() -> Self {
54 TaskPoolOptions {
55 min_total_threads: 1,
57 max_total_threads: usize::MAX,
58
59 io: TaskPoolThreadAssignmentPolicy {
61 min_threads: 1,
62 max_threads: 4,
63 percent: 0.25,
64 },
65
66 async_compute: TaskPoolThreadAssignmentPolicy {
68 min_threads: 1,
69 max_threads: 4,
70 percent: 0.25,
71 },
72
73 compute: TaskPoolThreadAssignmentPolicy {
75 min_threads: 1,
76 max_threads: usize::MAX,
77 percent: 1.0, },
79 }
80 }
81}
82
83impl TaskPoolOptions {
84 pub fn with_num_threads(thread_count: usize) -> Self {
86 TaskPoolOptions {
87 min_total_threads: thread_count,
88 max_total_threads: thread_count,
89 ..Default::default()
90 }
91 }
92
93 pub fn create_default_pools(&self) {
95 let total_threads = bevy_tasks::available_parallelism()
96 .clamp(self.min_total_threads, self.max_total_threads);
97 trace!("Assigning {} cores to default task pools", total_threads);
98
99 let mut remaining_threads = total_threads;
100
101 {
102 let io_threads = self
104 .io
105 .get_number_of_threads(remaining_threads, total_threads);
106
107 trace!("IO Threads: {}", io_threads);
108 remaining_threads = remaining_threads.saturating_sub(io_threads);
109
110 IoTaskPool::get_or_init(|| {
111 TaskPoolBuilder::default()
112 .num_threads(io_threads)
113 .thread_name("IO Task Pool".to_string())
114 .build()
115 });
116 }
117
118 {
119 let async_compute_threads = self
121 .async_compute
122 .get_number_of_threads(remaining_threads, total_threads);
123
124 trace!("Async Compute Threads: {}", async_compute_threads);
125 remaining_threads = remaining_threads.saturating_sub(async_compute_threads);
126
127 AsyncComputeTaskPool::get_or_init(|| {
128 TaskPoolBuilder::default()
129 .num_threads(async_compute_threads)
130 .thread_name("Async Compute Task Pool".to_string())
131 .build()
132 });
133 }
134
135 {
136 let compute_threads = self
139 .compute
140 .get_number_of_threads(remaining_threads, total_threads);
141
142 trace!("Compute Threads: {}", compute_threads);
143
144 ComputeTaskPool::get_or_init(|| {
145 TaskPoolBuilder::default()
146 .num_threads(compute_threads)
147 .thread_name("Compute Task Pool".to_string())
148 .build()
149 });
150 }
151 }
152}