Thanks to visit codestin.com
Credit goes to github.com

Skip to content

perf: reduce SQL round-trips and CPU overhead in scheduler hot paths#60

Merged
deepjoy merged 1 commit into
mainfrom
group-bench-perf
Mar 19, 2026
Merged

perf: reduce SQL round-trips and CPU overhead in scheduler hot paths#60
deepjoy merged 1 commit into
mainfrom
group-bench-perf

Conversation

@deepjoy

@deepjoy deepjoy commented Mar 19, 2026

Copy link
Copy Markdown
Owner

Summary

  • Eliminate unnecessary SQL round-trips across the task dispatch and completion hot paths, cutting dispatch_no_groups_500 latency by ~23% (166ms → 128ms)
  • Replace generic chrono datetime parser with a fixed-position byte parser for the known SQLite format
  • Add has_hierarchy fast-path flag (following existing has_tags pattern) to skip the active_children_count query when no parent-child tasks exist
  • Batch dependency resolution from 2+2N queries down to 2 using DELETE … RETURNING + single UPDATE … RETURNING
  • Add fast_dispatch mode that uses pop_next() (1 SQL) instead of peek_next() + gate + claim_task() (2 SQL) when no groups, pressure sources, or module caps are configured

Details

1. Inline last_insert_rowid (store/lifecycle/mod.rs)

insert_history was issuing a separate SELECT last_insert_rowid() query after every INSERT into task_history. The SqliteQueryResult already carries this value — use result.last_insert_rowid() directly, matching the existing pattern in complete_inner.

2. Fast datetime parsing (store/row_mapping.rs)

parse_datetime was calling chrono::NaiveDateTime::parse_from_str with a fallback — a generic parser invoked 2-4× per row_to_task_record. Replaced with a fixed-position byte parser that handles both "YYYY-MM-DD HH:MM:SS" and "YYYY-MM-DD HH:MM:SS.fff…".

3. has_hierarchy flag (store/mod.rs, scheduler/spawn/completion.rs)

handle_success was calling active_children_count (a SELECT COUNT(*) query) for every task completion, even when no tasks use parent-child hierarchy. Added an Arc<AtomicBool> flag to TaskStore — set to true when a task with parent_id is submitted — and skip the query when false. Follows the existing has_tags pattern exactly.

4. Batched dependency resolution (store/dependencies.rs)

resolve_dependents_inner previously used SELECT + DELETE + per-dependent COUNT + UPDATE (2+2N queries). Now uses DELETE FROM task_deps … RETURNING task_id followed by a single UPDATE tasks … WHERE id IN (…) AND NOT EXISTS (SELECT 1 FROM task_deps …) RETURNING id — always 2 queries regardless of fan-out. Applied the same DELETE … RETURNING optimization to fail_dependents_inner.

5. Fast dispatch path (scheduler/run_loop.rs, scheduler/builder.rs)

When no groups, pressure sources, resource monitoring, or module caps are configured, try_dispatch now uses pop_next() (atomic UPDATE+RETURNING, 1 SQL) instead of peek_next() + gate.admit() + claim_task() (2 SQL). Added an expiry filter to pop_next()'s inner SELECT so expired tasks are safely skipped. The slow path is preserved unchanged as a fallback.

Benchmark results

Benchmark Before After Change
dispatch_no_groups_500 166ms 128ms -23%
dispatch_one_group_500 235ms 170ms -28%
dispatch_group_scaling/100 234ms 164ms -30%
dep_fan_in_dispatch/50 17.7ms 14.3ms -19%
dep_fan_in_dispatch/100 34.5ms 27.4ms -19%

- Use result.last_insert_rowid() in insert_history instead of separate
  SELECT query, saving 1 round-trip per task completion
- Replace generic chrono datetime parser with fast fixed-position byte
  parser for the known SQLite format
- Add has_hierarchy flag to skip active_children_count query when no
  parent-child tasks exist
- Batch dependency resolution into 2 queries (DELETE RETURNING + single
  UPDATE RETURNING) instead of 2+2N
- Add fast dispatch path using pop_next() (1 SQL) instead of
  peek_next + gate + claim_task (2 SQL) when no groups, pressure
  sources, or module caps are configured

bench_dispatch_no_groups_500: ~166ms → ~128ms (-23%)
@deepjoy deepjoy enabled auto-merge (squash) March 19, 2026 07:32
@deepjoy deepjoy merged commit 2ab7b57 into main Mar 19, 2026
1 of 2 checks passed
@github-actions github-actions Bot mentioned this pull request Mar 19, 2026
deepjoy pushed a commit that referenced this pull request Mar 19, 2026
## 🤖 New release

* `taskmill`: 0.5.1 -> 0.5.2 (✓ API compatible changes)

<details><summary><i><b>Changelog</b></i></summary><p>

<blockquote>

## [0.5.2](v0.5.1...v0.5.2)
- 2026-03-19

### Other

- reduce SQL round-trips and CPU overhead in scheduler hot paths
([#60](#60))
- coalesce task completions into batched transactions
([#59](#59))
- reduce SQL round-trips in scheduler hot paths
([#57](#57))
</blockquote>


</p></details>

---
This PR was generated with
[release-plz](https://github.com/release-plz/release-plz/).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant