Writing a Concurrent "Task" Scheduler in Rust - Part 1.5
Date: April 22, 2026
In the previous article, I describe the requirements for my final project and share my testing code. In this section, I address some amendments made to the project guidelines.
As noted at the end of the previous article, the requirements for the project slightly shifted since writing. The amendment is as follows:
- Different kinds of tasks now have a resource load, which is a specified as
35%forCPUtasks and10%forIOtasks. - There must be at most 8 workers in the worker pool (I keep this generalized and simply limit the test to 8 workers).
- The collective resource usage across all workers must not surprass
100%, e.g., 2 workers forCPUand 3 workers forIOtasks is valid, but delegating 6 workers toIOinstead is not (as the total usage would be(2x) 35% + (6x) 10% = 130%). - Tasks musts be sent 20ms apart (so I guess I'm rewriting the arrival time and task dispatcher code?)
For what it's worth, this is a very uniform distribution.
- Both
IOandCPUtasks will take200ms
The lack of a variable system load is meant to simplify the project by foregoing heuristic analysis of worker threads. Though, I would like to explore this after the project is finished.
Thus, until additional amendments are made to the runtime requirements, this is the new testing code:
use rand::rngs::StdRng;
use rand::SeedableRng;
use rand::prelude::*;
use rand::distr::weighted::WeightedIndex;
use std::time::{Duration, SystemTime};
use crate::td::task::{Task, TaskKind};
use crate::td::pool::WorkerPool;
pub mod td;
fn main() {
let seed: u64 = 123456;
let mut rng = StdRng::seed_from_u64(seed);
let mut tasks = vec![];
let tasks_total = 500;
let arrival_time_0 = SystemTime::now() + Duration::new(5, 0);
let dist_taskkind = WeightedIndex::new(&[3, 7]).unwrap();
let mut arrival_time_offset_20ms = 0;
for id in 1..=tasks_total {
let kind = vec![TaskKind::CPU, TaskKind::IO][dist_taskkind.sample(&mut rng)].clone();
let duration = Duration::from_millis(200);
let arrival_time = arrival_time_0 + Duration::from_millis(20 * arrival_time_offset_20ms);
arrival_time_offset_20ms += 1;
tasks.push(Task{
id,
arrival_time,
kind,
duration,
});
}
// no need to sort anymore
tasks.reverse();
let pool = WorkerPool::new(8);
println!("Worker pool opened. Waiting for tasks...");
while !tasks.is_empty() {
if let Some(task) = tasks.last() && task.arrival_time <= SystemTime::now() {
println!("Dispatching task {:?}, which will take about {:.3?}s...", task.id, task.duration.as_secs_f32());
pool.execute_task(task.clone());
tasks.pop();
}
}
}