Summary
This experiment investigates rtos task priority. Full factorial of task priority levels, tick rate, stack size, and preemption threshold for latency and utilization.
The design varies 4 factors: task priority levels (levels), ranging from 4 to 16, tick rate hz (Hz), ranging from 100 to 1000, stack size bytes (bytes), ranging from 512 to 4096, and preemption threshold (level), ranging from 1 to 8. The goal is to optimize 2 responses: worst case latency us (us) (minimize) and cpu utilization pct (%) (maximize). Fixed conditions held constant across all runs include rtos = freertos, mcu clock = 240MHz.
A full factorial design was used to explore all 16 possible combinations of the 4 factors at two levels. This guarantees that every main effect and interaction can be estimated independently, at the cost of a larger experiment (16 runs).
Quadratic response surface models were fitted to capture potential curvature and factor interactions. The RSM contour plots below visualize how pairs of factors jointly affect each response.
Key Findings
For worst case latency us, the most influential factors were tick rate hz (48.8%), preemption threshold (26.5%), stack size bytes (16.7%). The best observed value was 26.0 (at task priority levels = 4, tick rate hz = 1000, stack size bytes = 512).
For cpu utilization pct, the most influential factors were preemption threshold (34.6%), stack size bytes (32.7%), tick rate hz (29.4%). The best observed value was 90.0 (at task priority levels = 16, tick rate hz = 100, stack size bytes = 512).
Recommended Next Steps
- Consider whether any fixed factors should be varied in a future study.
Experimental Setup
Factors
| Factor | Low | High | Unit |
task_priority_levels | 4 | 16 | levels |
tick_rate_hz | 100 | 1000 | Hz |
stack_size_bytes | 512 | 4096 | bytes |
preemption_threshold | 1 | 8 | level |
Fixed: rtos = freertos, mcu_clock = 240MHz
Responses
| Response | Direction | Unit |
worst_case_latency_us | ↓ minimize | us |
cpu_utilization_pct | ↑ maximize | % |
Configuration
{
"metadata": {
"name": "RTOS Task Priority",
"description": "Full factorial of task priority levels, tick rate, stack size, and preemption threshold for latency and utilization"
},
"factors": [
{
"name": "task_priority_levels",
"levels": [
"4",
"16"
],
"type": "continuous",
"unit": "levels"
},
{
"name": "tick_rate_hz",
"levels": [
"100",
"1000"
],
"type": "continuous",
"unit": "Hz"
},
{
"name": "stack_size_bytes",
"levels": [
"512",
"4096"
],
"type": "continuous",
"unit": "bytes"
},
{
"name": "preemption_threshold",
"levels": [
"1",
"8"
],
"type": "continuous",
"unit": "level"
}
],
"fixed_factors": {
"rtos": "freertos",
"mcu_clock": "240MHz"
},
"responses": [
{
"name": "worst_case_latency_us",
"optimize": "minimize",
"unit": "us"
},
{
"name": "cpu_utilization_pct",
"optimize": "maximize",
"unit": "%"
}
],
"settings": {
"operation": "full_factorial",
"test_script": "use_cases/69_rtos_task_priority/sim.sh"
}
}
Experimental Matrix
The Full Factorial Design produces 16 runs. Each row is one experiment with specific factor settings.
| Run | task_priority_levels | tick_rate_hz | stack_size_bytes | preemption_threshold |
| 1 | 4 | 1000 | 4096 | 8 |
| 2 | 16 | 100 | 512 | 8 |
| 3 | 4 | 1000 | 512 | 8 |
| 4 | 4 | 1000 | 4096 | 1 |
| 5 | 16 | 1000 | 4096 | 1 |
| 6 | 16 | 100 | 4096 | 1 |
| 7 | 16 | 1000 | 512 | 1 |
| 8 | 16 | 100 | 512 | 1 |
| 9 | 4 | 100 | 512 | 8 |
| 10 | 4 | 100 | 4096 | 1 |
| 11 | 16 | 1000 | 512 | 8 |
| 12 | 16 | 1000 | 4096 | 8 |
| 13 | 4 | 1000 | 512 | 1 |
| 14 | 16 | 100 | 4096 | 8 |
| 15 | 4 | 100 | 512 | 1 |
| 16 | 4 | 100 | 4096 | 8 |
Step-by-Step Workflow
1
Preview the design
$ doe info --config use_cases/69_rtos_task_priority/config.json
2
Generate the runner script
$ doe generate --config use_cases/69_rtos_task_priority/config.json \
--output use_cases/69_rtos_task_priority/results/run.sh --seed 42
3
Execute the experiments
$ bash use_cases/69_rtos_task_priority/results/run.sh
4
Analyze results
$ doe analyze --config use_cases/69_rtos_task_priority/config.json
5
Get optimization recommendations
$ doe optimize --config use_cases/69_rtos_task_priority/config.json
6
Multi-objective optimization
With 2 competing responses, use --multi to find the best compromise via Derringer–Suich desirability.
$ doe optimize --config use_cases/69_rtos_task_priority/config.json --multi
7
Generate the HTML report
$ doe report --config use_cases/69_rtos_task_priority/config.json \
--output use_cases/69_rtos_task_priority/results/report.html
Features Exercised
| Feature | Value |
| Design type | full_factorial |
| Factor types | continuous (all 4) |
| Arg style | double-dash |
| Responses | 2 (worst_case_latency_us ↓, cpu_utilization_pct ↑) |
| Total runs | 16 |
Analysis Results
Generated from actual experiment runs using the DOE Helper Tool.
Response: worst_case_latency_us
Top factors: tick_rate_hz (48.8%), preemption_threshold (26.5%), stack_size_bytes (16.7%).
ANOVA
| Source | DF | SS | MS | F | p-value |
| Source | DF | SS | MS | F | p-value |
| task_priority_levels | 1 | 10.5625 | 10.5625 | 0.010 | 0.9235 |
| tick_rate_hz | 1 | 390.0625 | 390.0625 | 0.376 | 0.5663 |
| stack_size_bytes | 1 | 45.5625 | 45.5625 | 0.044 | 0.8422 |
| preemption_threshold | 1 | 115.5625 | 115.5625 | 0.112 | 0.7520 |
| task_priority_levels*tick_rate_hz | 1 | 370.5625 | 370.5625 | 0.358 | 0.5759 |
| task_priority_levels*stack_size_bytes | 1 | 855.5625 | 855.5625 | 0.826 | 0.4052 |
| task_priority_levels*preemption_threshold | 1 | 45.5625 | 45.5625 | 0.044 | 0.8422 |
| tick_rate_hz*stack_size_bytes | 1 | 473.0625 | 473.0625 | 0.457 | 0.5292 |
| tick_rate_hz*preemption_threshold | 1 | 175.5625 | 175.5625 | 0.169 | 0.6977 |
| stack_size_bytes*preemption_threshold | 1 | 1580.0625 | 1580.0625 | 1.525 | 0.2717 |
| Error | 5 | 5180.8125 | 1036.1625 | | |
| Total | 15 | 9242.9375 | 616.1958 | | |
Pareto Chart
Main Effects Plot
Normal Probability Plot of Effects
Half-Normal Plot of Effects
Model Diagnostics
Response: cpu_utilization_pct
Top factors: preemption_threshold (34.6%), stack_size_bytes (32.7%), tick_rate_hz (29.4%).
ANOVA
| Source | DF | SS | MS | F | p-value |
| Source | DF | SS | MS | F | p-value |
| task_priority_levels | 1 | 0.2500 | 0.2500 | 0.001 | 0.9814 |
| tick_rate_hz | 1 | 20.2500 | 20.2500 | 0.049 | 0.8341 |
| stack_size_bytes | 1 | 25.0000 | 25.0000 | 0.060 | 0.8160 |
| preemption_threshold | 1 | 28.0900 | 28.0900 | 0.068 | 0.8053 |
| task_priority_levels*tick_rate_hz | 1 | 41.6025 | 41.6025 | 0.100 | 0.7645 |
| task_priority_levels*stack_size_bytes | 1 | 678.6025 | 678.6025 | 1.632 | 0.2575 |
| task_priority_levels*preemption_threshold | 1 | 63.2025 | 63.2025 | 0.152 | 0.7127 |
| tick_rate_hz*stack_size_bytes | 1 | 172.9225 | 172.9225 | 0.416 | 0.5474 |
| tick_rate_hz*preemption_threshold | 1 | 22.5625 | 22.5625 | 0.054 | 0.8250 |
| stack_size_bytes*preemption_threshold | 1 | 460.1025 | 460.1025 | 1.107 | 0.3410 |
| Error | 5 | 2078.6325 | 415.7265 | | |
| Total | 15 | 3591.2175 | 239.4145 | | |
Pareto Chart
Main Effects Plot
Normal Probability Plot of Effects
Half-Normal Plot of Effects
Model Diagnostics
Response Surface Plots
3D surfaces fitted with quadratic RSM. Red dots are observed data points.
cpu utilization pct stack size bytes vs preemption threshold
cpu utilization pct task priority levels vs preemption threshold
cpu utilization pct task priority levels vs stack size bytes
cpu utilization pct task priority levels vs tick rate hz
cpu utilization pct tick rate hz vs preemption threshold
cpu utilization pct tick rate hz vs stack size bytes
worst case latency us stack size bytes vs preemption threshold
worst case latency us task priority levels vs preemption threshold
worst case latency us task priority levels vs stack size bytes
worst case latency us task priority levels vs tick rate hz
worst case latency us tick rate hz vs preemption threshold
worst case latency us tick rate hz vs stack size bytes
Multi-Objective Optimization
When responses compete, Derringer–Suich desirability finds the best compromise.
Each response is scaled to a 0–1 desirability, then combined via a weighted geometric mean.
Overall Desirability
D = 0.9166
Per-Response Desirability
| Response | Weight | Desirability | Predicted | Dir |
worst_case_latency_us |
1.0 |
|
34.00 0.8625 34.00 us |
↓ |
cpu_utilization_pct |
1.5 |
|
90.00 0.9545 90.00 % |
↑ |
Recommended Settings
| Factor | Value |
task_priority_levels | 16 levels |
tick_rate_hz | 100 Hz |
stack_size_bytes | 4096 bytes |
preemption_threshold | 8 level |
Source: from observed run #11
Trade-off Summary
Sacrifice = how much worse than single-objective best.
| Response | Predicted | Best Observed | Sacrifice |
cpu_utilization_pct | 90.00 | 90.00 | +0.00 |
Top 3 Runs by Desirability
| Run | D | Factor Settings |
| #12 | 0.8217 | task_priority_levels=4, tick_rate_hz=100, stack_size_bytes=512, preemption_threshold=1 |
| #7 | 0.7018 | task_priority_levels=4, tick_rate_hz=1000, stack_size_bytes=512, preemption_threshold=8 |
Model Quality
| Response | R² | Type |
cpu_utilization_pct | 0.3362 | linear |
Full Multi-Objective Output
============================================================
MULTI-OBJECTIVE OPTIMIZATION
Method: Derringer-Suich Desirability Function
============================================================
Overall desirability: D = 0.9166
Response Weight Desirability Predicted Direction
---------------------------------------------------------------------
worst_case_latency_us 1.0 0.8625 34.00 us ↓
cpu_utilization_pct 1.5 0.9545 90.00 % ↑
Recommended settings:
task_priority_levels = 16 levels
tick_rate_hz = 100 Hz
stack_size_bytes = 4096 bytes
preemption_threshold = 8 level
(from observed run #11)
Trade-off summary:
worst_case_latency_us: 34.00 (best observed: 26.00, sacrifice: +8.00)
cpu_utilization_pct: 90.00 (best observed: 90.00, sacrifice: +0.00)
Model quality:
worst_case_latency_us: R² = 0.1531 (linear)
cpu_utilization_pct: R² = 0.3362 (linear)
Top 3 observed runs by overall desirability:
1. Run #11 (D=0.9166): task_priority_levels=16, tick_rate_hz=100, stack_size_bytes=4096, preemption_threshold=8
2. Run #12 (D=0.8217): task_priority_levels=4, tick_rate_hz=100, stack_size_bytes=512, preemption_threshold=1
3. Run #7 (D=0.7018): task_priority_levels=4, tick_rate_hz=1000, stack_size_bytes=512, preemption_threshold=8
Full Analysis Output
=== Main Effects: worst_case_latency_us ===
Factor Effect Std Error % Contribution
--------------------------------------------------------------
tick_rate_hz 9.8750 6.2058 48.8%
preemption_threshold -5.3750 6.2058 26.5%
stack_size_bytes 3.3750 6.2058 16.7%
task_priority_levels -1.6250 6.2058 8.0%
=== ANOVA Table: worst_case_latency_us ===
Source DF SS MS F p-value
-----------------------------------------------------------------------------
task_priority_levels 1 10.5625 10.5625 0.010 0.9235
tick_rate_hz 1 390.0625 390.0625 0.376 0.5663
stack_size_bytes 1 45.5625 45.5625 0.044 0.8422
preemption_threshold 1 115.5625 115.5625 0.112 0.7520
task_priority_levels*tick_rate_hz 1 370.5625 370.5625 0.358 0.5759
task_priority_levels*stack_size_bytes 1 855.5625 855.5625 0.826 0.4052
task_priority_levels*preemption_threshold 1 45.5625 45.5625 0.044 0.8422
tick_rate_hz*stack_size_bytes 1 473.0625 473.0625 0.457 0.5292
tick_rate_hz*preemption_threshold 1 175.5625 175.5625 0.169 0.6977
stack_size_bytes*preemption_threshold 1 1580.0625 1580.0625 1.525 0.2717
Error 5 5180.8125 1036.1625
Total 15 9242.9375 616.1958
=== Interaction Effects: worst_case_latency_us ===
Factor A Factor B Interaction % Contribution
------------------------------------------------------------------------
stack_size_bytes preemption_threshold -19.8750 30.6%
task_priority_levels stack_size_bytes -14.6250 22.5%
tick_rate_hz stack_size_bytes 10.8750 16.7%
task_priority_levels tick_rate_hz -9.6250 14.8%
tick_rate_hz preemption_threshold 6.6250 10.2%
task_priority_levels preemption_threshold -3.3750 5.2%
=== Summary Statistics: worst_case_latency_us ===
task_priority_levels:
Level N Mean Std Min Max
------------------------------------------------------------
16 8 64.7500 29.0898 26.0000 105.0000
4 8 63.1250 21.7416 34.0000 94.0000
tick_rate_hz:
Level N Mean Std Min Max
------------------------------------------------------------
100 8 59.0000 22.0713 34.0000 94.0000
1000 8 68.8750 27.8846 26.0000 105.0000
stack_size_bytes:
Level N Mean Std Min Max
------------------------------------------------------------
4096 8 62.2500 23.8492 26.0000 96.0000
512 8 65.6250 27.2970 34.0000 105.0000
preemption_threshold:
Level N Mean Std Min Max
------------------------------------------------------------
1 8 66.6250 30.1090 26.0000 105.0000
8 8 61.2500 19.9338 34.0000 96.0000
=== Main Effects: cpu_utilization_pct ===
Factor Effect Std Error % Contribution
--------------------------------------------------------------
preemption_threshold -2.6500 3.8683 34.6%
stack_size_bytes 2.5000 3.8683 32.7%
tick_rate_hz -2.2500 3.8683 29.4%
task_priority_levels -0.2500 3.8683 3.3%
=== ANOVA Table: cpu_utilization_pct ===
Source DF SS MS F p-value
-----------------------------------------------------------------------------
task_priority_levels 1 0.2500 0.2500 0.001 0.9814
tick_rate_hz 1 20.2500 20.2500 0.049 0.8341
stack_size_bytes 1 25.0000 25.0000 0.060 0.8160
preemption_threshold 1 28.0900 28.0900 0.068 0.8053
task_priority_levels*tick_rate_hz 1 41.6025 41.6025 0.100 0.7645
task_priority_levels*stack_size_bytes 1 678.6025 678.6025 1.632 0.2575
task_priority_levels*preemption_threshold 1 63.2025 63.2025 0.152 0.7127
tick_rate_hz*stack_size_bytes 1 172.9225 172.9225 0.416 0.5474
tick_rate_hz*preemption_threshold 1 22.5625 22.5625 0.054 0.8250
stack_size_bytes*preemption_threshold 1 460.1025 460.1025 1.107 0.3410
Error 5 2078.6325 415.7265
Total 15 3591.2175 239.4145
=== Interaction Effects: cpu_utilization_pct ===
Factor A Factor B Interaction % Contribution
------------------------------------------------------------------------
task_priority_levels stack_size_bytes 13.0250 32.6%
stack_size_bytes preemption_threshold 10.7250 26.9%
tick_rate_hz stack_size_bytes -6.5750 16.5%
task_priority_levels preemption_threshold -3.9750 10.0%
task_priority_levels tick_rate_hz -3.2250 8.1%
tick_rate_hz preemption_threshold -2.3750 6.0%
=== Summary Statistics: cpu_utilization_pct ===
task_priority_levels:
Level N Mean Std Min Max
------------------------------------------------------------
16 8 57.9625 15.2656 37.9000 77.1000
4 8 57.7125 16.7319 34.4000 90.0000
tick_rate_hz:
Level N Mean Std Min Max
------------------------------------------------------------
100 8 58.9625 18.1725 34.4000 90.0000
1000 8 56.7125 13.4126 40.1000 77.1000
stack_size_bytes:
Level N Mean Std Min Max
------------------------------------------------------------
4096 8 56.5875 15.1936 34.4000 77.1000
512 8 59.0875 16.6917 37.9000 90.0000
preemption_threshold:
Level N Mean Std Min Max
------------------------------------------------------------
1 8 59.1625 20.8480 34.4000 90.0000
8 8 56.5125 8.6243 43.0000 69.2000
Optimization Recommendations
=== Optimization: worst_case_latency_us ===
Direction: minimize
Best observed run: #12
task_priority_levels = 4
tick_rate_hz = 1000
stack_size_bytes = 512
preemption_threshold = 8
Value: 26.0
RSM Model (linear, R² = 0.2412, Adj R² = -0.0347):
Coefficients:
intercept +63.9375
task_priority_levels +0.0625
tick_rate_hz +3.4375
stack_size_bytes -7.0625
preemption_threshold -8.8125
RSM Model (quadratic, R² = 0.7357, Adj R² = -2.9652):
Coefficients:
intercept +12.7875
task_priority_levels +0.0625
tick_rate_hz +3.4375
stack_size_bytes -7.0625
preemption_threshold -8.8125
task_priority_levels*tick_rate_hz +13.3125
task_priority_levels*stack_size_bytes -4.1875
task_priority_levels*preemption_threshold -4.9375
tick_rate_hz*stack_size_bytes -4.0625
tick_rate_hz*preemption_threshold -7.0625
stack_size_bytes*preemption_threshold -0.3125
task_priority_levels^2 +12.7875
tick_rate_hz^2 +12.7875
stack_size_bytes^2 +12.7875
preemption_threshold^2 +12.7875
Curvature analysis:
tick_rate_hz coef=+12.7875 convex (has a minimum)
stack_size_bytes coef=+12.7875 convex (has a minimum)
preemption_threshold coef=+12.7875 convex (has a minimum)
task_priority_levels coef=+12.7875 convex (has a minimum)
Notable interactions:
task_priority_levels*tick_rate_hz coef=+13.3125 (synergistic)
tick_rate_hz*preemption_threshold coef=-7.0625 (antagonistic)
task_priority_levels*preemption_threshold coef=-4.9375 (antagonistic)
task_priority_levels*stack_size_bytes coef=-4.1875 (antagonistic)
tick_rate_hz*stack_size_bytes coef=-4.0625 (antagonistic)
stack_size_bytes*preemption_threshold coef=-0.3125 (antagonistic)
Predicted optimum (from linear model, at observed points):
task_priority_levels = 16
tick_rate_hz = 1000
stack_size_bytes = 512
preemption_threshold = 1
Predicted value: 83.3125
Surface optimum (via L-BFGS-B, linear model):
task_priority_levels = 4
tick_rate_hz = 100
stack_size_bytes = 4096
preemption_threshold = 8
Predicted value: 44.5625
Model quality: Weak fit — consider adding center points or using a different design.
Factor importance:
1. preemption_threshold (effect: -17.6, contribution: 45.5%)
2. stack_size_bytes (effect: 14.1, contribution: 36.5%)
3. tick_rate_hz (effect: 6.9, contribution: 17.7%)
4. task_priority_levels (effect: -0.1, contribution: 0.3%)
=== Optimization: cpu_utilization_pct ===
Direction: maximize
Best observed run: #11
task_priority_levels = 16
tick_rate_hz = 100
stack_size_bytes = 512
preemption_threshold = 8
Value: 90.0
RSM Model (linear, R² = 0.2708, Adj R² = 0.0057):
Coefficients:
intercept +57.8375
task_priority_levels -1.1875
tick_rate_hz -4.4250
stack_size_bytes +0.5125
preemption_threshold +6.2875
RSM Model (quadratic, R² = 0.7445, Adj R² = -2.8327):
Coefficients:
intercept +11.5675
task_priority_levels -1.1875
tick_rate_hz -4.4250
stack_size_bytes +0.5125
preemption_threshold +6.2875
task_priority_levels*tick_rate_hz -9.8250
task_priority_levels*stack_size_bytes -0.6125
task_priority_levels*preemption_threshold -1.6375
tick_rate_hz*stack_size_bytes +1.9500
tick_rate_hz*preemption_threshold +1.0000
stack_size_bytes*preemption_threshold +1.3875
task_priority_levels^2 +11.5675
tick_rate_hz^2 +11.5675
stack_size_bytes^2 +11.5675
preemption_threshold^2 +11.5675
Curvature analysis:
preemption_threshold coef=+11.5675 convex (has a minimum)
task_priority_levels coef=+11.5675 convex (has a minimum)
tick_rate_hz coef=+11.5675 convex (has a minimum)
stack_size_bytes coef=+11.5675 convex (has a minimum)
Notable interactions:
task_priority_levels*tick_rate_hz coef=-9.8250 (antagonistic)
tick_rate_hz*stack_size_bytes coef=+1.9500 (synergistic)
task_priority_levels*preemption_threshold coef=-1.6375 (antagonistic)
stack_size_bytes*preemption_threshold coef=+1.3875 (synergistic)
tick_rate_hz*preemption_threshold coef=+1.0000 (synergistic)
task_priority_levels*stack_size_bytes coef=-0.6125 (antagonistic)
Predicted optimum (from linear model, at observed points):
task_priority_levels = 4
tick_rate_hz = 100
stack_size_bytes = 4096
preemption_threshold = 8
Predicted value: 70.2500
Surface optimum (via L-BFGS-B, linear model):
task_priority_levels = 4
tick_rate_hz = 100
stack_size_bytes = 4096
preemption_threshold = 8
Predicted value: 70.2500
Model quality: Weak fit — consider adding center points or using a different design.
Factor importance:
1. preemption_threshold (effect: 12.6, contribution: 50.7%)
2. tick_rate_hz (effect: -8.9, contribution: 35.6%)
3. task_priority_levels (effect: 2.4, contribution: 9.6%)
4. stack_size_bytes (effect: -1.0, contribution: 4.1%)