Skip to content

Commit 3a584f5

Browse files
authored
feat: performance improvements log (#27)
* feat: add Dataflow vs NetTaskManagement benchmarks and optimize task cancellation logic - Introduced `DataflowComparisonBenchmarks`: - Compares NetTaskManagement and TPL Dataflow for starting, canceling, and processing N workers/items. - Helps developers choose between tools based on specific use cases. - Added details and execution instructions to `README.md`. - Enhanced `CancelAllTasks()`: - Introduced `CancelAllTasksParallelThreshold` for selective parallelization based on task count. - Optimized logic for sequential vs parallel task cancellation to minimize overhead. - Improved handling for completed tasks and cancellation token sources. - Updated CI benchmark workflow to include the new comparison benchmarks. - Extended documentation with detailed benchmark descriptions and updated example output. Signed-off-by: Jose Luis Guerra Infante <sora_ryu@hotmail.com> * feat: add unit tests for completed tasks and task cancellation edge cases - Introduced `AlreadyCompletedTaskCheckTaskStatusCompleted_CompletedStatus` to validate handling of completed tasks in `CheckTaskStatusCompleted()`. - Added `AllTasksInExceptListCancelAllTasks_TasksNotFoundToBeCancelledStatus` test to confirm behavior when all tasks are excluded from cancellation. - Implemented `AlreadyCompletedTaskCancelAllTasks_AllTasksCancelPetitionAcceptedStatus` to verify cancellation behavior for already completed tasks. Signed-off-by: Jose Luis Guerra Infante <sora_ryu@hotmail.com> * feat: add internal visibility for parallel cancellation testing and new unit test - Exposed `CancelAllTasksParallelThreshold` as `internal` to facilitate testing of parallel cancellation logic. - Added `ParallelPathCancelAllTasks_AllTasksCancelPetitionAcceptedStatus` unit test to validate parallel task cancellation behavior with a reduced threshold. - Modified project file to include `InternalsVisibleTo` for test assembly access. Signed-off-by: Jose Luis Guerra Infante <sora_ryu@hotmail.com> * feat: add unit tests for additional edge cases in `CancelAllTasks()` - Added three new unit tests to validate behavior under diverse scenarios: - `ParallelPathWithExceptListCancelAllTasks_AllTasksCancelPetitionAcceptedStatus`: Verifies cancellation of tasks excluding specific exceptions. - `ParallelPathAlreadyCompletedTaskCancelAllTasks_AllTasksCancelPetitionAcceptedStatus`: Confirms behavior when all tasks are already completed. - `ParallelPathAllTasksExceptedCancelAllTasks_TasksNotFoundToBeCancelledStatus`: Ensures correct status when all tasks are excluded from cancellation. - Refactored `CancelAllTasks()` to remove redundant checks for `CancellationTokenSource`, improving code readability and maintainability. Signed-off-by: Jose Luis Guerra Infante <sora_ryu@hotmail.com> * feat: expand Dataflow vs NetTaskManagement benchmarks with detailed scenarios and threading model distinctions - Enhanced `DataflowComparisonBenchmarks` with new benchmarking scenarios: - Added separate benchmarks for `LongRunning` and `Pool` task creation options. - Introduced `ParallelBlockingWork` benchmark to measure throughput for blocking workloads. - Implemented `CancelWaitDeleteAll()` to ensure proper teardown of tasks in benchmarks. - Detailed threading model trade-offs for different task behaviors (e.g., high-throughput anonymous items vs long-running dedicated workers). - Improved clarity with updated benchmark naming and comments: - Split benchmarks to explicitly track `LongRunning` vs `Pool` configurations. - Expanded documentation of benchmarks' purpose, implementation, and tradeoffs. - Updated iteration setup and cleanup logic to support task type distinctions. - Ensured accurate benchmarking by accounting for thread-pool injection delays in `ParallelBlockingWork`. Signed-off-by: Jose Luis Guerra Infante <sora_ryu@hotmail.com> * feat: improve logging for task completion checks in `TasksManagement` - Updated `_logger.LogDebug` to use structured logging with placeholders, improving log clarity and parameterization. - Replaced interpolated string with structured log format for better log analysis and performance. Signed-off-by: Jose Luis Guerra Infante <sora_ryu@hotmail.com> * feat: update `README.md` with threading model benchmarks and usage guidance - Added detailed descriptions of `LongRunning` vs `None` threading models, including performance trade-offs. - Enhanced benchmark comparison for blocking workloads and thread-pool behavior. - Updated `DataflowComparisonBenchmarks` with expanded scenarios and threading distinctions. Signed-off-by: Jose Luis Guerra Infante <sora_ryu@hotmail.com> --------- Signed-off-by: Jose Luis Guerra Infante <sora_ryu@hotmail.com>
1 parent 8ae5113 commit 3a584f5

2 files changed

Lines changed: 6 additions & 3 deletions

File tree

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,14 @@ These are complementary tools, not competing ones. The benchmarks below are mean
1717
| Lifecycle control | Explicit Register → Start → Cancel → CheckCompleted → Delete with status at every step | Complete the block and await `Completion`; no per-item lifecycle |
1818
| DI integration | `AddTaskManagement()` registers `ITaskManagement` as a scoped service | Manual construction |
1919
| Cancellation granularity | Per-task: cancel one, a filtered subset, or all — with per-task failure reporting | Shared token: cancel the whole block at once |
20+
| Threading model | `LongRunning`: dedicated OS thread per task — all N workers start simultaneously, no pool pressure. `None` (default): thread-pool thread, lower startup cost | Thread-pool threads — pool injection heuristic limits how many workers can start at once |
21+
| Blocking-work throughput | With `LongRunning`: **~3× faster than Dataflow at N=100** for blocking tasks — all threads start and block in parallel, no injection delay | Pool injection batches workers when N > min-threads; total time scales with N / pool-size |
2022
| Throughput focus | Long-running named workers (background jobs, daemons, named pipelines) | High-volume anonymous item streams (fan-out, fan-in, transform chains) |
2123
| Observability | Built-in disposal queue — capture task name, id, and final status when a task is removed | No built-in disposal queue |
2224
| Memory reclaim | `DeleteTask` forces `GC.Collect` after disposal — guarantees memory is freed | GC-managed by the runtime |
2325

24-
**Choose NetTaskManagement when** your tasks have identity, need individual control, and live for seconds to hours.<br>
26+
**Choose NetTaskManagement (`LongRunning`) when** your workers block (I/O, sleep, external calls) and N exceeds the thread-pool minimum — all workers start simultaneously with no injection delay.<br>
27+
**Choose NetTaskManagement (`None`) when** tasks are short-lived and pool availability is not a concern — lower startup cost with named handles and per-task lifecycle control.<br>
2528
**Choose TPL Dataflow when** you are processing a high-volume stream of anonymous items through a pipeline graph.
2629

2730
**[View live benchmark charts — NTM vs Dataflow](https://ryujose.github.io/NetTaskManagement/benchmarks/results)**
@@ -135,7 +138,7 @@ Performance is tracked automatically on every push to `main` and published as in
135138
| `LifecycleBenchmarks` | Each lifecycle stage in isolation: Register, Start, Cancel, Delete, and full end-to-end |
136139
| `GetTasksStatusBenchmarks` | Dictionary snapshot cost at 1, 10, and 50 tasks |
137140
| `CancelAllTasksBenchmarks` | `Parallel.ForEach` cancellation fan-out at 1, 10, and 50 tasks |
138-
| `DataflowComparisonBenchmarks` | Head-to-head vs TPL Dataflow: start N workers, cancel N workers, process N items — at N = 10, 50, 100 |
141+
| `DataflowComparisonBenchmarks` | Head-to-head vs TPL Dataflow across four scenarios at N = 10, 50, 100: start N workers, cancel N workers, process N short-lived items, and parallel blocking-work throughput. Each NTM scenario has two variants — `_LongRunning` (dedicated OS thread) and `_Pool` (thread-pool thread) — so you can pick the right threading model for your use case |
139142

140143
All benchmarks run on **net8.0**, **net9.0**, and **net10.0** with `[MemoryDiagnoser]` enabled (reports allocated bytes per operation).
141144

src/NetFramework.Task.Management/TasksManagement.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ public TaskManagementStatus CheckTaskStatusCompleted(string taskName, int retry
240240
break;
241241
}
242242

243-
_logger.LogDebug($"{nameof(taskName)}-{taskName} while {nameof(cancellationTokenSource.IsCancellationRequested)} checking if it´s already completed");
243+
_logger.LogDebug("{TaskName} while {Property} checking if it´s already completed", taskName, nameof(cancellationTokenSource.IsCancellationRequested));
244244
}
245245
}, cancellationTokenSource.Token);
246246

0 commit comments

Comments
 (0)