Refactored BinaryTypeCode to reserve 0..63 for FixObj slot indices, enabling direct array access for object wrappers. Introduced a new polymorphic type prefix system for properties whose runtime type differs from their declared type, with first/repeated occurrence markers and combined ref-tracking support. Unified wrapper slot caching for SGen and runtime types, improving performance and eliminating dictionary lookups in hot paths. Updated code generation, tests, and constants to use the new slot system. Added new settings and utility scripts. Overall, serialization is now faster, more robust, and extensible.
Activate FastWire encoding for both serialization and deserialization, using UTF-16 and fixed-width lengths for strings. WireMode is now public and defaults to FastWire. Removes unused ObjectEnd marker, clarifying object end handling. This improves string (de)serialization speed at the cost of larger output.
All FastWire-related code paths, fields, and options have been commented out in both AcBinarySerializer and AcBinaryDeserializer. This removes support for fixed-width integer and UTF-16 encoding, forcing the use of compact VarInt and UTF-8 encoding exclusively. The WireMode option is also commented out, so FastWire can no longer be selected. This change reduces output size and simplifies the codebase, but may impact serialization/deserialization speed for some scenarios.
Introduces a WireMode enum to select between Compact (VarInt + UTF-8) and Fast (fixed-width + UTF-16) wire formats for binary serialization. Updates AcBinarySerializerOptions to include a WireMode property (default: Fast). Serialization and deserialization logic now conditionally uses fixed-width or variable-length encoding for integers and strings based on the selected mode, enabling a tradeoff between output size and performance.
Refactored deserialization to use IBinaryInputBase abstraction, supporting both ArrayBinaryInput (byte[]) and SequenceBinaryInput (ReadOnlySequence<byte>). All context and methods are now generic over TInput, enabling zero-copy for arrays and true streaming for multi-segment sources. Internal logic (ReadValue, Populate, Skip, etc.) is specialized per input type, improving performance and flexibility. This enables future extensibility for other input sources and optimizes handling of large or segmented payloads.
Eliminate BinaryDeserializationContextClass and merge all buffer, pooling, and cache logic into a single sealed BinaryDeserializationContext. All pooling and state management is now handled directly by the context, reducing allocations and indirection. All deserialization entry points and internal logic are updated to use the new context class and pool. String interning, metadata, and array pooling are now managed within the unified context, improving performance and maintainability.
- Moved test data creation to BenchmarkTestDataProvider.cs and removed from Program.cs for better organization.
- Added [MessagePackObject]/[Key] attributes to all test models for explicit MessagePack serialization.
- Updated MessagePack benchmark to use MessagePackSerializerOptions.Standard.
- Improved AcBinaryDeserializer string cache with ASCII byte match to prevent hash collision bugs.
- Optimized AcBinarySerializer/Deserializer for string property handling and non-primitive writes.
- Set AcBinarySerializerOptions.UseMetadata default to true for safer deserialization.
Refactored binary deserialization to use a pooled BinaryDeserializationContextClass, eliminating per-call heap allocations and enabling cache reuse for string and intern caches. Introduced DeserializationContextClassPool for efficient context management. Updated all deserialization entry points to use the pool with proper disposal. Added efficient ReadOnlySequence<byte> support. Changed AcBinarySerializerOptions.UseMetadata default to false. These changes reduce GC pressure and improve performance, especially for high-throughput and WASM scenarios.
Refactor binary serializer to use a true two-pass process for string interning and object reference tracking. Adds a scan pass to identify duplicates and assigns cache indices deterministically in first-occurrence order. Updates wire format to write explicit cache indices after *First markers. Refactors InternEntry, removes marker rewriting, and updates deserializer to match new format. Improves performance, correctness, and robustness for complex object graphs with shared references and repeated strings.
Refactored AcBinarySerializer to write type property metadata inline
after the ObjectWithMetadata marker, eliminating the need for a
separate metadata footer section. Updated serialization, deserialization,
and diagnostic test logic to support the new inline metadata format.
Also updated settings.local.json to allow "Bash(git stash:*)" commands.
Introduce UseMetadata mode with FNV-1a property name hashing.
Write per-type property hashes to metadata footer for robust
property matching during deserialization. Remove legacy property
name table logic. Add ObjectWithMetadata marker and cachemap
logic for nested objects. Enable duplicate hash detection and
make UseMetadata default. Improves schema evolution support.
Reduce allocations by pooling int[] and object?[] arrays used for duplicate data and interned references during binary deserialization. Arrays are now rented and reused via ArrayPool<T>, with logic to clear or return them as appropriate. This improves performance and reduces GC pressure in steady-state scenarios.
Major refactor: merges string interning and object reference tracking (IId/Non-IId) into a unified position-based cache and footer in binary serialization. Wire format now uses cache indices for all references; hashcode/Id prefixes removed. Serialization and deserialization logic simplified, improving performance and maintainability. Legacy code paths and redundant dictionary lookups eliminated.
Update serializer and deserializer to use VarUInt for (position, cacheIndex) pairs in interned string footers, replacing fixed int32 format. This reduces serialized size and improves efficiency for small values. Adjust deserializer to read VarUInt pairs into a flat int[] array. Update comments and docs accordingly.
Replaces DupEntry[] with flat int[] for position-based string interning in AcBinaryDeserializer and AcBinarySerializer. Serializer now writes (position, cacheIndex) pairs as fixed int32s in bulk, and deserializer reads them with MemoryMarshal.Cast for ultra-fast, cache-friendly access. This eliminates per-pair parsing overhead and streamlines the hot path for string interning.
Refactored AcBinaryDeserializer to use a cached _nextDupPosition
for ultra-fast string interning (single int comparison). Updated
initialization/reset logic and streamlined RegisterInternedString
to avoid unnecessary array access and branching. Commented out
MinStringInternLength threshold checks to always register interned
strings. Simplified GetInternedString and made a minor update to
the serializer's analysis report wording. These changes improve
performance and reliability of string interning during
deserialization.
Implement a new position-based string interning mechanism in AcBinarySerializer/AcBinaryDeserializer. This approach tracks stream positions for interned strings, ensuring 100% reliable cache matching during deserialization, even when strings are skipped or reordered. The serializer now writes (position, cacheIndex) pairs in the footer for all repeated strings, and the deserializer uses this mapping for robust cache population. Removes the old buffer-based interned string logic, updates all relevant code paths, and simplifies interned string handling for greater correctness and maintainability. Also updates benchmarks and test data construction to use the new interning mode.
- Refactor all serializer options to use properties returning new instances (no shared mutable state); update all usages accordingly
- Extract AcSerializerOptions, BinaryTypeCode, and BinaryPropertyFilterContext to dedicated files for clarity and reuse
- Add DEBUG-only string interning analysis/reporting tools to AcBinarySerializer
- Improve AcBinarySerializer string property serialization with direct typed getter and SIMD-optimized ASCII path
- Increase benchmark/test warmup iterations and add JIT warmup delays for more reliable performance measurements
- Remove redundant usings and update documentation/comments throughout
- No breaking API changes, but static readonly options fields are now properties
- Make ReferenceHandlingMode type-aware; OnlyId fully supported for binary, All is default for JSON
- ReferenceHandling is now settable; add ThrowOnCircularReference option
- Always sort Id property first for IId types to optimize tracking
- Serialize/deserialize IId.Id without type marker when reference handling is enabled
- Contexts now delegate options-derived properties to Options
- Improve skip logic and property filter performance in binary serializer
- Update tests to explicitly set ReferenceHandlingMode.All
- Refactor internal APIs for clarity, safety, and efficiency
- Replace UseReferenceHandling bool with ReferenceHandlingMode enum across all serializers and options
- Move AcBinary string interning to footer (no header shifting); remove bloom filter
- Overhaul benchmark console: multi-serializer, grouped/colorized results, CSV/log output, more test data
- Set UseMetadata = false by default (header property names unused)
- Update all context Reset/Pool logic for new options signature
- Update AcJson/Toon serializers for new reference handling
- Update tests and usages for new enum-based options
- Add Newtonsoft.Json to benchmark dependencies
- Misc: code cleanups, improved comments, clarify logic
Replaces flat object reference dictionary with per-type identity maps in deserializer, improving type safety and efficiency for IId types. TypeMetadataWrapper now uses cached typed delegates for reference ID access. Centralizes complex type detection and exposes IsComplexType and TypedIdGetter in metadata. Updates all registration and lookup logic to use wrappers, removes obsolete metadata cache, and ensures thread-safe, type-aware reference handling throughout. Comments out legacy code for easier review and rollback.
Unifies IId-based reference handling for binary serialization and deserialization. Introduces BinaryDeserializationContextClass for heap-based IId tracking, refactors IdentityMap<TId> for unified object storage, and removes legacy IIdReferenceTracker logic. Updates deserializer to use the new infrastructure for all IId types (int, long, Guid) and correct wire formats. Enhances tests for reference identity and object graph integrity. Improves code clarity and maintainability.
Adds robust IId<T>-based reference deduplication to both serialization and deserialization. Objects with the same type and Id are now treated as the same reference, reducing output size and ensuring correct reference identity in complex graphs.
Key changes:
- TypeMetadataBase: Adds IdAccessorType, typed Id getters, and precomputed property arrays for zero-boxing and fast access.
- AcSerializerCommon: Introduces IIdReferenceTracker for efficient (Type, Id) → object mapping.
- SerializationReferenceTracker: Now supports both ReferenceEquals and IId-based tracking for scanning and writing.
- AcBinarySerializer: Reference scan uses IId-aware deduplication, skipping types that don't need tracking.
- AcBinaryDeserializer: Adds per-context IId caches to ensure reference identity on deserialization.
- PropertyAccessorBase: Adds IsComplexType for fast scan decisions.
- Populate/Chain: Integrated with new IId cache for correct deduplication.
- Tests: Adds/updates tests for IId identity, cross-type safety, and diagnostics.
- Benchmarks: Adds WithRef/NoRef and AcJson vs System.Text.Json.
- Documentation: Includes detailed implementation plan and rationale.
No breaking changes for types that do not use IId. Zero-boxing for int/long/Guid Ids. Reference identity is now preserved for all IId objects.
Introduce Roslyn Source Generator for AcBinary serialization, generating optimized Serialize/Deserialize methods for types marked with [AcBinarySerializable]. Integrate generator as analyzer in core, tests, and benchmarks. Update metadata to detect generated serializers. Add benchmarks and integration tests to validate performance and correctness. Update project files and internals visibility for testing. Existing runtime serialization remains as fallback.
Major overhaul of serialization/deserialization infrastructure:
- Introduced unified Chain API for binary/JSON, enabling multi-deserialization/population with strong IId reference identity (critical for Blazor/DXGrid).
- Added base classes for property accessors/setters and centralized type metadata.
- Implemented ChainReferenceTracker and shared IIdCollectionMergeHelper for reference tracking and collection merging.
- Refactored property access logic to use typed delegates for primitives/enums.
- Updated extension methods and replaced legacy chain/populate interfaces.
- Improved error handling and diagnostics.
- Added comprehensive tests for chain API and reference preservation.
- Minor fixes and performance optimizations throughout.
Previously, the string cache hash function only used the first 4 bytes and length, causing collisions for property names like "Creator" and "Created" in WASM. This led to incorrect property assignments and deserialization errors. The new ComputeStringHashFull function now hashes all bytes for strings up to 32 bytes, eliminating these collisions. Extensive comments document the bug, its impact, and the necessity of the fix.
Introduces detailed, opt-in diagnostic logging for binary serialization and deserialization in SignalR server and client code. Adds type and binary-level diagnostics, including hex dumps and header parsing, to aid debugging of protocol and type mismatches. Improves string hash function in the binary deserializer to avoid collisions. Diagnostics are consistent and structured, and can be enabled independently on server, client, and response message classes. No impact on normal operation unless diagnostics are enabled.
Major overhaul of binary serializer/deserializer tests: split and expand test coverage for primitives, objects, navigation, generics, circular refs, and edge cases. Fix critical bugs in property skipping, string interning, type mismatch diagnostics, nullable assignment, and VarInt decoding. Add WASM-optimized deserialization options with string caching. Switch SignalR compression from Brotli to Gzip and introduce GzipHelper. Add comprehensive StockTaking test models and real-world bug reproductions. Improve diagnostics, test discovery, and add benchmark/utility scripts.
- Introduced AcJsonSerializer/AcJsonDeserializer in AyCode.Core.Serializers.Jsons, optimized for IId<T> reference and circular reference handling.
- Added AcJsonSerializerOptions/AcSerializerOptions for configurable reference handling and max depth.
- Implemented fast-path streaming (Utf8JsonReader/Writer) with fallback to DOM for reference scenarios.
- Added type metadata/property accessor caching for performance.
- Provided robust object/collection population with merge semantics for IId<T> collections.
- Added AcJsonDeserializationException for detailed error reporting.
- Implemented UnifiedMergeContractResolver for Newtonsoft.Json, supporting JsonNoMergeCollectionAttribute to control merge behavior.
- Added IdAwareCollectionMergeConverter<TItem, TId> for merging IId<T> collections by ID.
- Included helpers for ID extraction and semantic ID generation.
- Added DeepPopulateWithMerge extension for deep merging.
- Optimized with frozen dictionaries, pre-encoded property names, and context pooling.
- Ensured compatibility with both System.Text.Json and Newtonsoft.Json.