Skip to content

Commit 15d2889

Browse files
committed
Expose LightweightTrace composite value encoding
1 parent 53e7464 commit 15d2889

File tree

1 file changed

+51
-19
lines changed
  • IncrementalGeneratorExtensions.Content/Datacute/IncrementalGeneratorExtensions

1 file changed

+51
-19
lines changed

IncrementalGeneratorExtensions.Content/Datacute/IncrementalGeneratorExtensions/LightweightTrace.cs

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,16 @@ public static class LightweightTrace
2121
{
2222
private const int Capacity = 1024;
2323

24-
private const int KeyValueShift = 1 << 10;
25-
private const int MapValue = 1 << 28;
24+
/// <summary>
25+
/// The stride used to encode a composite key where <c>key = id + (value * CompositeValueShift)</c>.
26+
/// Exposed to clarify how counters/events pack both an ID and a value into a single <see cref="int"/>.
27+
/// </summary>
28+
public const int CompositeValueShift = 1 << 10; // 1024 distinct IDs per value bucket
29+
/// <summary>
30+
/// A flag bit used in composite keys to indicate that the encoded value should be mapped via <c>eventNameMap</c>.
31+
/// This lets values represent enum-like categories instead of plain numbers when formatting output.
32+
/// </summary>
33+
public const int MapValueFlag = 1 << 28;
2634

2735
private static readonly DateTime StartTime = DateTime.UtcNow;
2836
private static readonly Stopwatch Stopwatch = Stopwatch.StartNew();
@@ -57,7 +65,7 @@ public static class LightweightTrace
5765
/// <param name="eventId">The ID of the event to log.</param>
5866
/// <param name="value">The value associated with the event, which can be used for additional context or categorization.</param>
5967
/// <param name="mapValue">If true, the value is treated as a mapped value when generating the diagnostic log.</param>
60-
public static void Add(int eventId, int value, bool mapValue = false) => Add(eventId + value * KeyValueShift, mapValue);
68+
public static void Add(int eventId, int value, bool mapValue = false) => Add(EncodeKey(eventId, value, mapValue));
6169
/// <summary>
6270
/// Adds an event to the trace log with the specified numeric event ID.
6371
/// </summary>
@@ -66,14 +74,14 @@ public static class LightweightTrace
6674
public static void Add(int eventId, bool mapValue = false)
6775
{
6876
var index = Interlocked.Increment(ref _index) % Capacity;
69-
Events[index] = (Stopwatch.ElapsedTicks, eventId | (mapValue ? MapValue : 0));
77+
Events[index] = (Stopwatch.ElapsedTicks, eventId | (mapValue ? MapValueFlag : 0));
7078
#if !DATACUTE_EXCLUDE_GENERATORSTAGE
71-
if ((eventId / KeyValueShift) != Convert.ToInt32(GeneratorStage.MethodExit))
79+
if ((eventId / CompositeValueShift) != Convert.ToInt32(GeneratorStage.MethodExit))
7280
{
73-
IncrementCount(GeneratorStage.MethodCall, eventId % KeyValueShift, true);
81+
IncrementCount(GeneratorStage.MethodCall, eventId % CompositeValueShift, true);
7482
}
7583
#else
76-
IncrementCount(eventId % KeyValueShift);
84+
IncrementCount(eventId % CompositeValueShift);
7785
#endif
7886
}
7987

@@ -114,7 +122,7 @@ public static void AppendTrace(this StringBuilder stringBuilder, Dictionary<int,
114122
var textAndValue = GetTextAndValue(eventNameMap, eventId);
115123
stringBuilder.AppendFormat("{0:o} [{1:000}] {2}",
116124
StartTime.AddTicks(timestamp),
117-
eventId % KeyValueShift,
125+
eventId % CompositeValueShift,
118126
textAndValue)
119127
.AppendLine();
120128
}
@@ -170,7 +178,7 @@ public static void AppendTrace(this StringBuilder stringBuilder, Dictionary<int,
170178
/// <param name="counterId">The ID of the counter to increment.</param>
171179
/// <param name="value">The value associated with the counter, which can be used for additional context or categorization.</param>
172180
/// <param name="mapValue">If true, the value is treated as a mapped value when generating the diagnostic log.</param>
173-
public static void IncrementCount(int counterId, int value, bool mapValue = false) => Counters.AddOrUpdate(counterId + value * KeyValueShift + (mapValue ? MapValue : 0), 1, (_, count) => count + 1);
181+
public static void IncrementCount(int counterId, int value, bool mapValue = false) => Counters.AddOrUpdate(EncodeKey(counterId, value, mapValue), 1, (_, count) => count + 1);
174182

175183
/// <summary>
176184
/// Decrements the value of a given key by 1.
@@ -183,7 +191,7 @@ public static void AppendTrace(this StringBuilder stringBuilder, Dictionary<int,
183191
/// <param name="counterId">The ID of the counter to decrement.</param>
184192
/// <param name="value">The value associated with the counter, which can be used for additional context or categorization.</param>
185193
/// <param name="mapValue">If true, the value is treated as a mapped value when generating the diagnostic log.</param>
186-
public static void DecrementCount(int counterId, int value, bool mapValue = false) => Counters.AddOrUpdate(counterId + value * KeyValueShift + (mapValue ? MapValue : 0), -1, (_, count) => count - 1);
194+
public static void DecrementCount(int counterId, int value, bool mapValue = false) => Counters.AddOrUpdate(EncodeKey(counterId, value, mapValue), -1, (_, count) => count - 1);
187195

188196
/// <summary>
189197
/// Gets a string with the current cache performance metrics.
@@ -199,27 +207,51 @@ public static void AppendCounts(this StringBuilder stringBuilder, Dictionary<int
199207
}
200208

201209
// Order by key for a consistent, readable output
202-
foreach (var kvp in Counters.OrderBy(kvp => kvp.Key % KeyValueShift).ThenBy(kvp => kvp.Key))
210+
foreach (var kvp in Counters.OrderBy(kvp => kvp.Key % CompositeValueShift).ThenBy(kvp => kvp.Key))
203211
{
204212
int counterId = kvp.Key;
205213
long count = kvp.Value;
206214

207215
var textAndValue = GetTextAndValue(eventNameMap, counterId);
208216
stringBuilder.AppendFormat(
209217
"[{0:000}] {1}: {2}",
210-
counterId % KeyValueShift, textAndValue, count)
218+
counterId % CompositeValueShift, textAndValue, count)
211219
.AppendLine();
212220
}
213221
}
214222

223+
/// <summary>
224+
/// Encodes a composite key combining an ID and a value into a single int.
225+
/// Set <paramref name="mapValue"/> when the value represents a categorical/enum mapping rather than a numeric measurement.
226+
/// </summary>
227+
/// <param name="id">The base ID (0..CompositeValueShift-1).</param>
228+
/// <param name="value">The associated value bucket or enum ordinal.</param>
229+
/// <param name="mapValue">True to mark the value as mapped (name lookup) instead of numeric.</param>
230+
public static int EncodeKey(int id, int value, bool mapValue = false) => id + (value * CompositeValueShift) + (mapValue ? MapValueFlag : 0);
231+
232+
/// <summary>
233+
/// Decodes a composite key into its ID, value, and mapped-value flag.
234+
/// </summary>
235+
/// <param name="key">The composite key previously produced by <see cref="EncodeKey"/> or any API that accepts (id,value).</param>
236+
/// <param name="id">The extracted base ID.</param>
237+
/// <param name="value">The extracted associated value.</param>
238+
/// <param name="isMappedValue">True if the value should be mapped by name for display.</param>
239+
public static void DecodeKey(int key, out int id, out int value, out bool isMappedValue)
240+
{
241+
isMappedValue = (key & MapValueFlag) != 0;
242+
var unflagged = key & ~MapValueFlag;
243+
id = unflagged % CompositeValueShift;
244+
value = unflagged / CompositeValueShift;
245+
}
246+
215247
private static string GetTextAndValue(Dictionary<int, string> eventNameMap, int key)
216248
{
217-
int id = key % KeyValueShift;
218-
int value = key / KeyValueShift;
249+
int id = key % CompositeValueShift;
250+
int value = key / CompositeValueShift;
219251

220-
if ((key & MapValue) != 0)
252+
if ((key & MapValueFlag) != 0)
221253
{
222-
value = (key & ~MapValue) / KeyValueShift;
254+
value = (key & ~MapValueFlag) / CompositeValueShift;
223255
}
224256

225257
string text = null;
@@ -233,9 +265,9 @@ private static string GetTextAndValue(Dictionary<int, string> eventNameMap, int
233265
}
234266

235267
string valueText = null;
236-
if (key >= KeyValueShift)
268+
if (key >= CompositeValueShift)
237269
{
238-
if (eventNameMap != null && (key & MapValue) != 0)
270+
if (eventNameMap != null && (key & MapValueFlag) != 0)
239271
{
240272
eventNameMap.TryGetValue(value, out valueText);
241273
}
@@ -245,7 +277,7 @@ private static string GetTextAndValue(Dictionary<int, string> eventNameMap, int
245277
}
246278
}
247279

248-
return (key >= KeyValueShift) ? $"{text} ({valueText})" : text;
280+
return (key >= CompositeValueShift) ? $"{text} ({valueText})" : text;
249281
}
250282

251283
/// <summary>

0 commit comments

Comments
 (0)