You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: plan/planning/brief.md
+10-54Lines changed: 10 additions & 54 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,25 +4,28 @@
4
4
5
5
Remove `netstandard2.0` from the main library's `<TargetFrameworks>`, retaining only `net10.0;net9.0;net8.0`.
6
6
This eliminates all conditional compilation guards that existed solely to support the older target, simplifies `Bitwise.cs` to use `BitOperations.LeadingZeroCount` unconditionally, and cleans up a branching code path in `HistogramLogReader.cs`.
7
+
The three per-framework Release `PropertyGroup` conditions in the csproj are collapsed into a single unconditional `PropertyGroup` as part of this change.
7
8
The spec file `build-system.md` must be updated to reflect the new target list.
8
9
9
10
Previous NuGet releases remain available on NuGet.org for consumers on .NET Framework or older runtimes.
10
11
11
12
## Category
12
13
13
-
`performance`
14
+
`chore`
14
15
15
-
Performance is a primary motivation: the netstandard2.0 code path uses a slow, lookup-table-based `LeadingZeroCount` rather than the `BitOperations` hardware intrinsic.
16
-
This change also delivers simplification and a reduction in build artefacts, but the performance impact on a hot instrumentation path is the key driver.
16
+
This is a maintenance and simplification task.
17
+
The hardware-intrinsic `LeadingZeroCount` path (`#if NET5_0_OR_GREATER`) is already compiled in for all net8.0+ builds; removing the fallback does not change the compiled output for any net8.0, net9.0, or net10.0 consumer.
18
+
No performance improvement is delivered to existing net8.0+ consumers — the change reduces build artefacts, removes dead code, and simplifies the codebase.
17
19
18
20
## Affected Files (confirmed by exploration)
19
21
20
22
| File | Change required |
21
23
|------|----------------|
22
-
|`HdrHistogram/HdrHistogram.csproj`| Remove `netstandard2.0` from `<TargetFrameworks>` (line 4); delete the netstandard2.0 `PropertyGroup` condition (lines 36-39) |
24
+
|`HdrHistogram/HdrHistogram.csproj`| Remove `netstandard2.0` from `<TargetFrameworks>` (line 4); delete the netstandard2.0 `PropertyGroup` condition (lines 36-39); collapse the three per-framework Release `PropertyGroup` conditions (lines 24-34) into a single `Condition="'$(Configuration)' == 'Release'"` block|
23
25
|`HdrHistogram/Utilities/Bitwise.cs`| Remove `#if NET5_0_OR_GREATER` guards (lines 25-29, 32-44); inline `IntrinsicNumberOfLeadingZeros` body directly into `NumberOfLeadingZeros`; delete the entire `Bitwise.Imperative` class (lines 55-109) |
24
26
|`HdrHistogram/HistogramLogReader.cs`| Remove `#if NETSTANDARD2_0` block in `IsComment()` (lines 241-248); keep the `char` overload unconditionally |
25
27
|`spec/tech-standards/build-system.md`| Remove `netstandard2.0` from the TargetFrameworks code block (line 25) and from the target table (line 33) |
-[ ] The three per-framework Release `PropertyGroup` conditions are collapsed into a single `Condition="'$(Configuration)' == 'Release'"` block
41
+
-[ ]`LeadingZeroCountBenchmarkBase.cs` no longer references `Bitwise.Imperative`; the benchmarking project compiles cleanly
37
42
-[ ] All unit tests pass on net8.0, net9.0, and net10.0
38
43
-[ ]`spec/tech-standards/build-system.md` no longer references `netstandard2.0`
39
44
@@ -58,63 +63,14 @@ This is low-risk but provides a regression anchor if `Bitwise.cs` is touched aga
58
63
59
64
There is no need to add tests for `IsComment` — it is a private static helper with trivial logic.
60
65
61
-
## Benchmark Strategy
62
-
63
-
### Why benchmarks are required
64
-
65
-
This is a `performance` category issue.
66
-
The stated motivation is that the netstandard2.0 fallback path is slower.
67
-
Benchmarks must confirm that the hardware-intrinsic path is indeed faster and that the improvement is observable at both micro and end-to-end level.
68
-
69
-
### Existing relevant benchmarks
70
-
71
-
`HdrHistogram.Benchmarking/LeadingZeroCount/` already contains benchmarks for this exact area:
72
-
73
-
-`LeadingZeroCountBenchmarkBase.cs` — benchmarks `Bitwise.NumberOfLeadingZeros()` (intrinsic path, line 119) and `Bitwise.Imperative.NumberOfLeadingZeros()` (fallback, line 130)
74
-
75
-
These benchmarks were written to compare the two implementations.
76
-
After `Bitwise.Imperative` is deleted, the `ImperativeImplementation` benchmark method must be removed or updated.
77
-
78
-
### Benchmark development plan
79
-
80
-
**Phase 1 — Baseline (before any code changes):**
81
-
82
-
1. Run the existing `LeadingZeroCount` benchmarks in Release mode against the current code to capture baseline metrics for both the intrinsic and imperative paths.
83
-
Record: Mean, StdDev, Allocated, Op/s.
84
-
2. If an end-to-end benchmark for `RecordValue` throughput exists (check `Recording/`), run it too.
85
-
86
-
**Phase 2 — Implementation:**
87
-
88
-
3. Apply the changes described above.
89
-
4. Remove the `ImperativeImplementation` benchmark method from `LeadingZeroCountBenchmarkBase.cs` (it references the deleted class).
90
-
5. Update `Program.cs``BenchmarkSwitcher` if the benchmark class is renamed.
91
-
92
-
**Phase 3 — Validation:**
93
-
94
-
6. Re-run the `LeadingZeroCount` micro-benchmarks and any `Recording` end-to-end benchmarks.
95
-
7. Produce a before/after table (Mean, Allocated, Op/s) and include it in the PR description.
96
-
97
-
**Metrics that matter:**
98
-
99
-
| Metric | Relevance |
100
-
|--------|-----------|
101
-
| Mean throughput (Op/s) | Primary — shows intrinsic is faster than the lookup table |
102
-
| Allocated (bytes) | Secondary — both paths should allocate nothing; confirms no regression |
103
-
| GC Gen0/Gen1 collections | Sanity check — should remain zero for both paths |
104
-
105
-
A micro-benchmark improvement in `LeadingZeroCount` that does not translate to observable improvement in `RecordValue` throughput is expected (the intrinsic is already used on net8.0+), but the benchmark result still validates correctness and code simplification.
106
-
107
66
## Risks and Open Questions
108
67
109
68
1.**Benchmark class references `Bitwise.Imperative`** — deleting the class will break the `ImperativeImplementation` benchmark at compile time.
110
-
The benchmark must be updated in the same PR.
69
+
The benchmark must be updated in the same PR (listed in Affected Files above).
111
70
112
71
2.**NuGet package surface** — removing a target framework is a breaking change for consumers on netstandard2.0.
113
72
This is explicitly accepted: "Previous NuGet releases will remain available."
114
73
The PR description should note this prominently and suggest a major-version bump or release notes entry.
115
74
116
75
3.**No other conditional compilation found** — the grep over the codebase confirmed only two files contain the relevant `#if` blocks.
117
76
Low risk of missing anything.
118
-
119
-
4.**Documentation file `PropertyGroup` condition** — the existing per-framework Release `PropertyGroup` conditions for net8.0, net9.0, net10.0 (lines 24-34 of the csproj) can be collapsed into a single unconditional `PropertyGroup Condition="'$(Configuration)' == 'Release'"` as shown in `build-system.md`.
120
-
This is a tidy-up that is in scope but should be confirmed with the implementer.
0 commit comments