Skip to content
AI-assisted, verified against source

Changelog v3.4.7 (2025-01-21)

Version 3.4.7 (2025-01-21)

Full Changelog

Type Category Lookup Optimization

Introduced TypeCategory flags enum and pre-computed lookup table for O(1) type dispatch, replacing sequential if-chain conditionals in hot paths.

New Files:

  • TypeCategory.cs - Flags enum (Numeric, Boolean, Json, Text, DateTime, Date, NeedsEscape, CastToText, Binary, Time) and TypeCategoryLookup static class with 128-element array for instant type classification
  • ParameterParsers.cs - Delegate array for O(1) parameter parser lookup by NpgsqlDbType

Changes:

  • TypeDescriptor now has a Category property computed once at construction via lookup table
  • Boolean properties (IsNumeric, IsJson, IsText, etc.) are now computed from Category using bitwise operations
  • NpgsqlRestEndpoint.cs and PgConverters.cs use bitwise category checks for type dispatch

Benchmark Results:

OperationBeforeAfterImprovement
Type category lookup (18 types)22.6 ns6.6 ns70% faster
TypeDescriptor construction232.8 ns164.2 ns29% faster
Parser delegate lookup7.6 ns5.9 ns23% faster
Combined type check (bitwise vs properties)7.97 ns4.94 ns38% faster
Serialization type check (1000 rows)5,572 ns4,060 ns27% faster

Note: While micro-benchmarks show significant improvements, real-world endpoint throughput gains are modest (1-5%) since type dispatch is a small fraction of total request time compared to database I/O and serialization.

Additional Allocation Optimizations

Parameter Logging String Allocations

Replaced string.Concat() with paramIndex.ToString() in 8 logging paths with direct StringBuilder.Append(int) calls, eliminating intermediate string allocations for each logged parameter.

Before:

csharp
csharp
cmdLog!.AppendLine(string.Concat("-- $", paramIndex.ToString(), " ", ...));

After:

csharp
csharp
cmdLog!.Append("-- $").Append(paramIndex).Append(' ').Append(...).AppendLine(p);

Cache Key String Reuse

Cache key string (cacheKeys.ToString()) was being called 3-6 times per cached request. Now computed once and reused:

csharp
csharp
string? cacheKeyString = cacheKeys?.ToString();
// Reused in all cache Get/AddOrUpdate calls

Impact: Eliminates 8+ string allocations per parameter-heavy request (logging) and 2-5 allocations per cached request (cache keys).


Comments