- Rewrote SequenceBinaryInput for lazy TryGet iteration (no segment array allocation), zero-copy access to segment backing arrays, and efficient cross-boundary reads using a reusable ArrayPool scratch buffer.
- Added Release() to IBinaryInputBase; now always called after deserialization to return scratch buffer.
- BufferWriterChunkSize is now mutable; set to 4096 for SignalR protocol for better pipe alignment.
- Added and updated documentation: detailed input buffer lifecycle, cross-boundary handling, and new BINARY_ISSUES.md and SIGNALR_ISSUES.md for known limitations and planned optimizations.
- No breaking API changes; improves performance, memory usage, and diagnostics for multi-segment binary deserialization.
- Add BINARY_IMPLEMENTATION.md with internal architecture and perf details
- Link new implementation doc from all relevant documentation
- Change default ReferenceHandlingMode to OnlyId
- Change default UseStringInterning to All
- Add InternalsVisibleTo for Mango.Nop.Core
Changed default WireMode to Compact and string interning to Attribute in AcBinarySerializerOptions. Added Bash commands in settings.local.json for fetching and processing Cysharp/MemoryPack files via GitHub API and curl/python scripts.
Refactored property enumeration in AcBinarySourceGenerator to match runtime ordering and filtering using a new helper. Null checks for reference types are now unconditional in generated code. Changed default string interning mode to All. Added InternalsVisibleTo for FruitBank.Common. Writer attribute checks now only apply to source-defined types.
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.
Refactored EmitReadString to use a switch for O(1) dispatch of string wire formats, improving performance and clarity. Updated comments to document the new approach and its benefits. Removed the UseGeneratedCode property from AcBinarySerializerOptions.
Changed AcBinarySerializerOptions defaults: UseMetadata is now false, UseGeneratedCode is now true. Improved IId reference tests by adding UseMetadata option, new null and reference identity assertions, and refactored assertion order for clarity. These changes ensure more robust test coverage and align default serializer behavior with expected usage.
Refactor test methods to use [DataRow] for parameterized testing of UseSgen and UseMeta combinations. Dynamically set AcBinarySerializerOptions in tests and add diagnostic output. Swap default values in AcBinarySerializerOptions: UseMetadata is now true, UseGeneratedCode is now false. This affects default serializer behavior across tests and usages.
- Emit special serialization logic for properties declared as System.Object, using value.GetType() and writing type name metadata for correct polymorphic deserialization.
- Add IsObjectDeclaredType to PropInfo to support this logic.
- Update scan pass to use runtime type for object properties.
- Adjust IId reference test to ensure circular reference coverage.
- Default UseGeneratedCode to true in serializer options.
Introduce new test models for circular refs, update tests to stress reference handling, and enhance deserializer to support ObjectRefFirst/WithMetadataRefFirst type codes. Fix intern cache index assignment, track generated readers in TypeMetadataWrapper, and disable UseGeneratedCode by default. Update benchmarks for reliability and diagnostics. These changes strengthen reference resolution, circular ref support, and performance.
Refactored binary serializer to use a single wrapper slot per SGen type for both metadata registration and reference tracking. Removed slot-based IdentityMap arrays and scan pass tracking methods, replacing them with wrapper-based TryTrack logic. Updated generated code to use wrapper slots for all slot-based operations. Changed UseMetadata registration to use a MetadataSeen flag on the wrapper. Added fast slot-indexed wrapper access in context base. Default UseMetadata option is now false. Simplifies and optimizes SGen tracking, reducing dictionary lookups and unifying tracking logic.
- Set `[AcBinarySerializable(true)]` on all SharedTestModels types
- Default `UseMetadata` to true for property hash footer
- Reset slotted ID maps and cache indices in serializer context
- Reduce test iterations for DEBUG builds to speed up runs
- Add debug comments in context `Clear()` method
Added compile-time scan requirement flags to SerializableClassInfo and PropInfo, and implemented recursive analysis to determine if scan work is needed for reference tracking and string interning. Updated code generation to emit scan code only when necessary, with runtime guards based on compile-time analysis. Changed AcBinarySerializerOptions.UseMetadata default to false. Increased JIT wait in Program.cs for more reliable benchmarking. These changes reduce unnecessary scan calls and improve performance.
Adds EnableMetadataFeature to [AcBinarySerializable], allowing types to opt out of inline metadata even when global UseMetadata is enabled. Source generator, serializer, and deserializer now respect this flag for child and element types. Default UseMetadata is set to true. Enables fine-grained control over serialization overhead and compatibility.
AcBinarySourceGenerator now reads feature flags from [AcBinarySerializable], enabling selective code generation for ID tracking, reference handling, and string interning. Property ordering is always alphabetical, removing "Id"-first sorting for IId types. Reference tracking code is only emitted when features are enabled. TypeMetadataBase and AcBinarySerializer runtime logic now respect these flags. Default options updated: ReferenceHandlingMode is All, UseMetadata is false. Test models explicitly disable all features. Comments and code structure improved for clarity.
Improve generated serialization code to match runtime behavior for metadata emission and reference tracking. Markerless types now respect UseMetadata, ensuring type markers are written when required. Ref tracking guards for IId and non-IId types are unified to match scan pass logic. Generated writers are always used when available. Default UseMetadata is now true for consistent metadata 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.
Refactor AcBinarySerializer to use ReadOnlySpan<T> for bulk writing of primitive arrays and List<T>, replacing multiple specialized methods with a single TryWritePrimitiveCollection. This improves efficiency and reduces code duplication. Change default string interning mode to Attribute (opt-in). Update generated code path to allow reference tracking but not string interning. Adjust benchmarks to test correct serializer options. Reorder options for clarity.
- Integrated MemoryPack as a serializer in the benchmark suite
- Added [MemoryPackable] and [MemoryPackIgnore] to test models
- Enabled AcBinary source generation by default
- Updated benchmark app to include MemoryPack and focus on key serializers
- Added MemoryPack NuGet references to projects
- Refactored AcBinarySerializer.WriteString flag handling
Implement write plan mechanism for string interning and IId object reference tracking. Scan pass now builds pre-computed WriteDuplicateEntry instructions, eliminating hot path IdentityMap lookups and redundant getter calls in the write pass. Update BinarySerializationContext, tracking visit indices and managing write plan array. Refactor ScanInternString and TryTrack methods to record visit indices and build write instructions for all duplicate occurrences. Update write pass logic to consume write plan entries. Add debug validation for scan/write pass order. Update benchmarks and test harness. Set UseGeneratedCode default to false. Improves performance for scenarios with interning and reference tracking.
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.
Major internal refactor: AcBinarySerializer and BinarySerializationContext are now generic on TOutput : BinaryOutputBase, enabling JIT devirtualization and eliminating virtual dispatch in hot serialization loops. All serialization logic (WriteValue, WriteObject, WriteArray, etc.) is now generic on TOutput and delegates buffer operations to the output instance (ArrayBinaryOutput or BufferWriterBinaryOutput). Context pooling is now per output type. All buffer management is moved to output classes. The public API is unchanged, but the internal architecture is now fully generic and ready for further JIT optimizations. Also disables the source generator and sets UseMetadata=false by default.
Introduce ArrayBinaryOutput, BufferWriterBinaryOutput, BinaryOutputBase, and IBinaryOutput for flexible, efficient serialization to pooled arrays and streaming buffers. Refactor AcBinaryHubProtocol to use new output for SignalR. Make UseMetadata runtime-settable in AcBinarySerializerOptions. Update QuickBenchmark for new options. Enables allocation-free, extensible binary serialization infrastructure.
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.
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.
Implemented LZ4 compression/decompression in pure managed code, compatible with all platforms including WASM. Added new helpers (`Lz4`, `Lz4Compressor`, `Lz4Decompressor`) and a `Lz4CompressionMode` enum. Updated `AcBinarySerializerOptions` to support compression, and modified all relevant serializer methods to apply LZ4 when enabled. Benchmarks and buffer handling updated to support zero-allocation compression. No native dependencies required.
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.
Refactor IId reference tracking with a new allocation-free, high-performance IdentityMap<TId> using bitmaps and pooled hash tables. Add async context cleanup for serializers, with pre-rented arrays for improved hot-path performance. Update AcSerializerOptions and context classes for better pooling, immutability, and platform support. Centralize and optimize array pooling and clearing to reduce memory pressure and GC impact.
Replaces boolean UseStringInterning with StringInterningMode enum for more granular control (None, Attribute, All). Introduces AcStringInternAttribute for per-property interning configuration. Updates all usages and documentation to reflect the new approach, ensuring explicit and flexible string interning behavior in serialization. Default mode is now All to preserve legacy behavior.
- 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
- Add "profiler" mode for memory profiling AcBinary serialization
- Reduce warmup iterations from 10 to 5 for faster benchmarks
- Save large test binary output to separate .output file (hex dump)
- Improve robustness of AcBinary vs MessagePack result comparison
- Use DisplayName for test data in result output for clarity
- Optimize AcBinary string interning: use single contiguous buffer
- Update WriteFooterStrings to avoid per-string allocations
- Clarify WithoutReferenceHandling() disables string interning for speed
- 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
- 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.
- 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.
Added support for optional/default parameters in SignalR method invocation. The hub now fills in missing arguments with default values when not provided, and throws if required parameters are missing. Added comprehensive tests for default parameter handling, a new handler method for testing, and a tag constant. Also improved code style with C# pattern matching and made UseStringCaching immutable.
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.
Introduces FixStr encoding (type codes 34–65) for short ASCII/UTF8 strings up to 31 bytes, combining type and length in one byte for improved space and speed. Adds SIMD-optimized bulk copy methods for double, float, and Guid arrays. Updates deserializer to handle FixStr codes efficiently. Adjusts tiny int encoding range to free up FixStr space. Disables metadata and string interning in shallow copy options. Improves performance and reduces overhead for common serialization scenarios.
- 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.