mirror of
https://github.com/esphome/esphome.git
synced 2026-06-24 14:55:05 +00:00
[core] Replace scheduler pool vector with unbounded intrusive freelist (#16172)
This commit is contained in:
@@ -101,8 +101,8 @@ static void Scheduler_SetTimeout(benchmark::State &state) {
|
||||
Component dummy_component;
|
||||
|
||||
// Register 3 timeouts then call() — realistic worst case where multiple
|
||||
// components schedule in the same loop iteration. Keeps item count within
|
||||
// the recycling pool (MAX_POOL_SIZE=5) to avoid spurious malloc/free.
|
||||
// components schedule in the same loop iteration. warm_pool fills the
|
||||
// freelist so acquire/recycle never falls back to malloc.
|
||||
static constexpr int kBatchSize = 3;
|
||||
static_assert(kInnerIterations % kBatchSize == 0, "kInnerIterations must be divisible by kBatchSize");
|
||||
warm_pool(scheduler, &dummy_component, kBatchSize, 1000);
|
||||
@@ -209,9 +209,9 @@ static void Scheduler_SetTimeout_ExceedPool(benchmark::State &state) {
|
||||
Scheduler scheduler;
|
||||
Component dummy_component;
|
||||
|
||||
// Register 10 timeouts then call() — exceeds MAX_POOL_SIZE=5 to measure
|
||||
// the performance cliff when the recycling pool is exhausted and items
|
||||
// must be malloc'd/freed.
|
||||
// Register 10 timeouts then call() — larger working set than the 3-item
|
||||
// batches above. With the unbounded freelist, warm_pool preallocates 10
|
||||
// items so this measures steady-state, not malloc cliff.
|
||||
static constexpr int kBatchSize = 10;
|
||||
static_assert(kInnerIterations % kBatchSize == 0, "kInnerIterations must be divisible by kBatchSize");
|
||||
warm_pool(scheduler, &dummy_component, kBatchSize, 1000);
|
||||
|
||||
@@ -221,14 +221,10 @@ script:
|
||||
- id: test_full_pool_reuse
|
||||
then:
|
||||
- lambda: |-
|
||||
ESP_LOGI("test", "Phase 6: Testing pool size limits after Phase 5 items complete");
|
||||
ESP_LOGI("test", "Phase 6: Testing pool reuse after Phase 5 items complete");
|
||||
|
||||
// At this point, all Phase 5 timeouts should have completed and been recycled.
|
||||
// The pool should be at its maximum size (5).
|
||||
// Creating 10 new items tests that:
|
||||
// - First 5 items reuse from the pool
|
||||
// - Remaining 5 items allocate new (pool empty)
|
||||
// - Pool doesn't grow beyond MAX_POOL_SIZE of 5
|
||||
// Phase 5 timeouts have completed and been recycled. The freelist is unbounded;
|
||||
// creating 10 new items reuses from it and only allocates fresh when empty.
|
||||
|
||||
auto *component = id(test_sensor);
|
||||
int full_reuse_count = 10;
|
||||
|
||||
@@ -180,16 +180,22 @@ async def test_scheduler_pool(
|
||||
# Verify pool behavior
|
||||
assert pool_recycle_count > 0, "Should have recycled items to pool"
|
||||
|
||||
# Check pool metrics
|
||||
if pool_recycle_count > 0:
|
||||
max_pool_size = 0
|
||||
for line in log_lines:
|
||||
if match := recycle_pattern.search(line):
|
||||
size = int(match.group(1))
|
||||
max_pool_size = max(max_pool_size, size)
|
||||
# Pool is unbounded; the cap was the source of the churn it was meant to prevent.
|
||||
assert pool_full_count == 0, (
|
||||
f"Pool should never report full (got {pool_full_count})"
|
||||
)
|
||||
|
||||
# Pool can grow up to its maximum of 5
|
||||
assert max_pool_size <= 5, f"Pool grew beyond maximum ({max_pool_size})"
|
||||
# Verify the pool actually grew past the old MAX_POOL_SIZE=5 cap.
|
||||
# Phase 5 + Phase 6 schedule 8 + 10 same-component timeouts respectively, so the
|
||||
# observed peak should comfortably exceed 5. Without this lower-bound check, a
|
||||
# silent regression that re-introduced a small cap could pass the test above.
|
||||
max_pool_size = 0
|
||||
for line in log_lines:
|
||||
if match := recycle_pattern.search(line):
|
||||
max_pool_size = max(max_pool_size, int(match.group(1)))
|
||||
assert max_pool_size > 5, (
|
||||
f"Pool should grow past the old cap of 5; observed peak {max_pool_size}"
|
||||
)
|
||||
|
||||
# Log summary for debugging
|
||||
print("\nScheduler Pool Test Summary (Python Orchestrated):")
|
||||
|
||||
Reference in New Issue
Block a user