Refactored AcBinaryDeserializer to read the type code marker byte only once per property, eliminating redundant PeekByte/ReadByte calls and improving efficiency. Updated all property population branches to use the already-consumed type code. Adjusted handling of nested complex objects to rewind the marker byte when needed. Modified TryReadAndSetTypedValue to assume the marker is already consumed, removing unnecessary reads. Exception messages now report the actual type code read.
Added UseGeneratedCode option (default true) to AcBinarySerializerOptions and exposed it in the serialization context. The generated code fast path is now gated by this option, allowing users to enable or disable source-generated serialization. These changes improve deserialization performance, code clarity, and configurability.
Pre-caches TypeMetadataWrapper instances for complex properties,
eliminating repeated GetWrapper dictionary lookups in serialization
and deserialization. Adds ComplexPropertyIndex and ComplexPropertyCount
fields, and PropertyTypeWrappers array to TypeMetadataWrapper. Refactors
scan, write, and populate passes to use cached wrappers, improving
performance for deep and polymorphic object graphs. Updates benchmarks
to focus on FastMode variants. No breaking changes; internal efficiency
improved.
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.
Introduced markerless serialization/deserialization for non-nullable value type properties when UseMetadata is false, eliminating type marker bytes for int, long, double, etc. Added ExpectedTypeCode to property accessors/setters to enable this optimization. Refactored property loops in serializer/deserializer for performance and clarity. Default UseMetadata is now false. Improves speed and reduces stream size for common value types while maintaining compatibility for complex types.
- 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.
Move CacheMap building to dedicated method for efficiency.
Remove incremental cache logic and SourceHashes field.
Simplify property population and update documentation.
Improves performance and code clarity.
Refactored deserialization logic to use inline metadata for UseMetadata mode, replacing footer-based property hash lookup. Context now tracks inline metadata entries and builds cache maps incrementally per source type. Unified property population for both metadata modes. Updated TypeMetadataWrapper to manage cache map and source hashes per context. Improved robustness for runtime source type changes and streamlined object skipping logic. Updated method signatures to use BinaryPropertySetterBase abstraction.
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.
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.
Move IdentityMap and IdAccessorType to dedicated file and update all usages. Introduce pooling and cache-friendly optimizations for small int keys and hash tables, minimizing allocations and speeding up resets. Update buffer sizes and profiling loops. Add extensive comments and preserve old implementation for reference. This prepares the codebase for more efficient serialization reference tracking.
- Unify and clarify object reference tracking for IId and non-IId types
- Always write/read Id as a normal property with type marker for IId types
- For non-IId types (All mode), use hashcode prefix for reference tracking
- Remove special Id prefix logic; all properties use type markers
- Centralize hashcode registration logic in deserializer
- Improve error handling for missing references
- Refactor tests to cover all ReferenceHandlingMode values and verify both data integrity and reference identity
- Add hex dump utility for debugging serialized bytes
- Make TypeMetadataBase.SourceType public for better diagnostics
- 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
- Introduced PropertyMetadataBase to unify property metadata and dynamic getter logic, now shared by PropertyAccessorBase and PropertySetterBase.
- Moved PropertyAccessorType enum to PropertyMetadataBase.
- Replaced all GetDynamicValue usages with GetValue for consistent property access in serializers/deserializers.
- Refactored PropertyAccessorBase and PropertySetterBase inheritance and responsibilities.
- Added MaxStringInternLength option to AcBinarySerializerOptions for configurable string interning.
- Improved collection deserialization: clear destination if source is empty.
- Added AyCode.Core.Serializers.Console project for performance profiling (with MessagePack comparison).
- Updated solution file to include new project and build configs.
- Minor code cleanups and documentation improvements.
Move strongly-typed getter/setter logic and PropertyAccessorType enum into PropertyAccessorBase and PropertySetterBase, eliminating duplication in binary accessor classes. Expose direct typed getter/setter methods and new SetValueTyped/SetToDefault helpers. Rename ObjectGetter to DynamicGetter and update all serializers/deserializers to use GetDynamicValue. Centralize default value logic and improve performance by reducing boxing/unboxing. This unifies and streamlines property accessor infrastructure across all serializers.
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.
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.
Refactored deserialization to use a unified PopulateObjectCore method, replacing PopulateObjectMerge and PopulateObjectNested to reduce duplication. Improved and centralized IId collection merge logic, with automatic detection and handling in merge mode. Reference ID registration is now consistent for reused objects and collections. Simplified SetPropertyToDefault to set collections to null. Updated documentation and clarified merge mode handling throughout. These changes improve maintainability, consistency, and robustness of deserialization.
- Changed TestStatus enum to use non-sequential values (5, 10, 20, ...)
- Updated related tests and deserialization logic for new enum values
- Changed PropertySkip marker from 253 to 191 to avoid TinyInt conflicts
- PropertySkip now only written for null references, not empty values
- Improved handling of skipped enum and nullable properties in deserializer
- Enhanced compiled property setter for nullable types
- Added comprehensive int serialization tests, including edge cases
- Fixed namespace casing and added missing using directive
Refactored object serialization to use fixed property order and a new PropertySkip marker for default/null values, removing property count and index overhead. Updated deserialization logic to handle skip markers and set defaults efficiently. Added WritePropertyOrSkip and SetPropertyToDefault methods for single-pass, boxing-free property handling. SkipObject now throws for new format. Updated BinaryTypeCode, .gitignore, and settings.local.json.
Switch to deterministic property index-based serialization/deserialization for improved performance and cross-platform consistency. Properties are now ordered alphabetically and accessed by index, enabling O(1) lookups and eliminating string/dictionary overhead. Introduce thread-local metadata caches, refactor metadata and populate logic, optimize string interning and enum handling, and remove legacy name-based code paths. Update diagnostics and documentation for clarity and maintainability.