Skip to content

Version 2.0.0

Compare
Choose a tag to compare
@StringEpsilon StringEpsilon released this 13 Nov 19:13
· 14 commits to main since this release

Breaking

  • Now targets .NET 8.0 and .NET 9.0
  • PhpTokenizer class is now internal.
  • Removed support for net6.0 and net7.0.
  • The default implicit type for numeric values is now int instead of long
    1.x: PhpSerialization.Deserialize("i:42;") == 42L
    2.x: PhpSerialization.Deserialize("i:42;") == 42
  • Changed the signature of [PhpPropery(long)] to [PhpPropery(int)] to align with the above change.

Features

  • Added PhpSerialization.DeserializeUtf8(ReadOnlySpan<byte>) overloads for cases in which consumers directly work with
    UTF8 inputs and can skip the re-encoding.
  • Added PhpSerializationFilter attribute base class, allowing customization of class and struct member serialization.
    See the PhpSerializationFilterTest for an example. See also Issue #33.

Regular changes

  • Integers and doubles without a value now give a better error message (i:; and d:;).

Performance

  • Reduced time to decode / re-encode the input string.
  • Reduced memory allocations both in the input re-encoding and the deserialization.
  • Delay the materialization of strings when deserializing. This can avoid string allocations entirely for integers,
    doubles and booleans.
  • Improved performance for implicit deserialization of integers as well as minor improvements for implicit
    deserialization of arrays.
  • Improved serialization performance for strings, integers, IList<T>, ExpandoObject, Dictionaries and PhpDynamicObject

Internal

Split the deserialization into 3 phases:

  1. Validation of the input and counting of the data tokens.
  2. Parsing of the input into tokens
  3. Deserializations of the tokens into the target C# objects/structs.

In version 1.4 and prior, this was a 2 step process. This is slightly slower on some inputs, but overall a little
neater because we're cleanly separating the tasks.


Some benchmark results:

Version Input Mean Allocated
1.4.0 a:0:{} 61.78 ns 248 B
2.0.0 a:0:{} 29.81 ns 80 B
1.4.0 a:3:{i:0;s:5:"Hello";i:1;s:5:"World";i:2;s:6:"FooBar";} 243.96 ns 816 B
2.0.0 a:3:{i:0;s:5:"Hello";i:1;s:5:"World";i:2;s:6:"FooBar";} 149.83 ns 352 B
1.4.0 b:1; 50.49 ns 208 B
2.0.0 b:1; 21.65 ns 72 B
1.4.0 i:2147483647; 79.66 ns 296 B
2.0.0 i:2147483647; 32.13 ns 72 B
1.4.0 N; 45.53 ns 184 B
2.0.0 N; 20.57 ns 48 B
1.4.0 O:8:"stdClass":0:{} 97.71 ns 400 B
2.0.0 O:8:"stdClass":0:{} 56.86 ns 176 B
1.4.0 O:8:"stdClass":2:{s:4:"John";d:3.14;s:4:"Jane";d:2.718;} 307.86 ns 992 B
2.0.0 O:8:"stdClass":2:{s:4:"John";d:3.14;s:4:"Jane";d:2.718;} 206.99 ns 504 B
1.4.0 s:12:"Hello World!"; 72.20 ns 296 B
2.0.0 s:12:"Hello World!"; 36.02 ns 96 B