Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# This is only for local build
PackageRedirects.props

## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
Expand Down
24 changes: 24 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "${workspaceFolder}/artifacts/bin/bench/debug/bench.dll",
"args": [],
"cwd": "${workspaceFolder}/bench",
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach"
}
]
}
41 changes: 41 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/serde.msgpack.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary;ForceNoAlign"
],
"problemMatcher": "$msCompile"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/serde.msgpack.sln",
"/property:GenerateFullPaths=true",
"/consoleloggerparameters:NoSummary;ForceNoAlign"
],
"problemMatcher": "$msCompile"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"--project",
"${workspaceFolder}/serde.msgpack.sln"
],
"problemMatcher": "$msCompile"
}
]
}
18 changes: 18 additions & 0 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project>
<Import Project="$(MSBuildThisFileDirectory)PackageRedirects.props" Condition="Exists('$(MSBuildThisFileDirectory)PackageRedirects.props')" />
<ItemGroup>
<!-- Remove all items from PackageReference if they are in the PackageRedirect ItemGroup with a matching PackageName
element. Then add a ProjectReference to the project with the item identity in PackageRedirect. -->
<_ExcludePackage Include="@(PackageRedirect)" Exclude="@(PackageReference)">
<MatchOnMetadata>PackageName</MatchOnMetadata>
<ProjectPath>%(PackageName)</ProjectPath>
</_ExcludePackage>
<_ExcludeProjects Include ="@(_ExcludePackage->Metadata('ProjectPath'))" />
<ProjectReference Include="@(PackageRedirect)" Exclude="@(_ExcludeProjects)">
<ReferenceOutputAssembly>%(ReferenceOutputAssembly)</ReferenceOutputAssembly>
<OutputItemType>%(OutputItemType)</OutputItemType>
</ProjectReference>

<PackageReference Remove="%(PackageRedirect.PackageName)" />
</ItemGroup>
</Project>
13 changes: 0 additions & 13 deletions bench/DataGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,6 @@ public static T GenerateSerialize<T>() where T : Serde.ISerializeProvider<T>

}

public static Location CreateLocation() => new Location
{
Id = 1234,
Address1 = "The Street Name",
Address2 = "20/11",
City = "The City",
State = "The State",
PostalCode = "abc-12",
Name = "Nonexisting",
PhoneNumber = "+0 11 222 333 44",
Country = "The Greatest"
};

public static byte[] GenerateDeserialize<T>()
{
if (typeof(T) == typeof(LoginViewModel))
Expand Down
14 changes: 3 additions & 11 deletions bench/DeserializeFromString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,13 @@

namespace Benchmarks
{
[GenericTypeArguments(typeof(Location), typeof(LocationWrap))]
public class DeserializeFromString<T, U>
[GenericTypeArguments(typeof(Location))]
public class DeserializeFromString<T>
where T : Serde.IDeserializeProvider<T>
where U : Serde.IDeserializeProvider<T>
{
private byte[] value = null!;

private readonly IDeserialize<T> _proxy = T.DeserializeInstance;
private readonly IDeserialize<T> _manualProxy = U.DeserializeInstance;
private readonly IDeserialize<T> _proxy = T.Instance;

[GlobalSetup]
public void Setup()
Expand All @@ -32,11 +30,5 @@ public void Setup()

[Benchmark]
public T SerdeMsgPack() => Serde.MsgPack.MsgPackSerializer.Deserialize<T, IDeserialize<T>>(value, _proxy);

[Benchmark]
public T SerdeMsgPackManual() => Serde.MsgPack.MsgPackSerializer.Deserialize<T, IDeserialize<T>>(value, _manualProxy);

// DataContractJsonSerializer does not provide an API to serialize to string
// so it's not included here (apples vs apples thing)
}
}
4 changes: 2 additions & 2 deletions bench/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
}

var loc1 = MessagePackSerializer.Deserialize<Location>(msg1);
var loc2 = Serde.MsgPack.MsgPackSerializer.Deserialize<Location, LocationWrap>(msg1, LocationWrap.Instance);
var loc2 = Serde.MsgPack.MsgPackSerializer.Deserialize<Location>(msg1);

Console.WriteLine("Checking correctness of serialization: " + (loc1 == loc2));
if (loc1 != loc2)
Expand All @@ -31,5 +31,5 @@ Serialization is not correct
}

var config = DefaultConfig.Instance.AddDiagnoser(MemoryDiagnoser.Default);
var summary = BenchmarkSwitcher.FromAssembly(typeof(DeserializeFromString<,>).Assembly)
var summary = BenchmarkSwitcher.FromAssembly(typeof(DeserializeFromString<>).Assembly)
.Run(args, config);
118 changes: 2 additions & 116 deletions bench/SampleTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,18 @@ public partial class LoginViewModel
}

[GenerateSerialize, GenerateDeserialize]
[MessagePackObject]
[MessagePackObject(keyAsPropertyName: true)]
[SerdeTypeOptions(MemberFormat = MemberFormat.None)]
public partial record Location
{
[Key(0)]
public int Id { get; set; }
[Key(1)]
public string Address1 { get; set; }
[Key(2)]
public string Address2 { get; set; }
[Key(3)]
public string City { get; set; }
[Key(4)]
public string State { get; set; }
[Key(5)]
public string PostalCode { get; set; }
[Key(6)]
public string Name { get; set; }
[Key(7)]
public string PhoneNumber { get; set; }
[Key(8)]
public string Country { get; set; }

public static Location Sample => new Location
Expand All @@ -52,110 +44,4 @@ public partial record Location
Country = "The Greatest"
};
}

public sealed partial class LocationWrap : IDeserialize<Location>, IDeserializeProvider<Location>
{
public static LocationWrap Instance { get; } = new();
static IDeserialize<Location> IDeserializeProvider<Location>.DeserializeInstance => Instance;
private LocationWrap() { }

public static ISerdeInfo SerdeInfo { get; } = Serde.SerdeInfo.MakeCustom(
"Location",
typeof(Location).GetCustomAttributesData(),
[
("id", Int32Proxy.SerdeInfo, typeof(Location).GetProperty("Id")!),
("address1", StringProxy.SerdeInfo, typeof(Location).GetProperty("Address1")!),
("address2", StringProxy.SerdeInfo, typeof(Location).GetProperty("Address2")!),
("city", StringProxy.SerdeInfo, typeof(Location).GetProperty("City")!),
("state", StringProxy.SerdeInfo, typeof(Location).GetProperty("State")!),
("postalCode", StringProxy.SerdeInfo, typeof(Location).GetProperty("PostalCode")!),
("name", StringProxy.SerdeInfo, typeof(Location).GetProperty("Name")!),
("phoneNumber", StringProxy.SerdeInfo, typeof(Location).GetProperty("PhoneNumber")!),
("country", StringProxy.SerdeInfo, typeof(Location).GetProperty("Country")!)
]);

Benchmarks.Location Serde.IDeserialize<Benchmarks.Location>.Deserialize(IDeserializer deserializer)
{
int _l_id = default !;
string _l_address1 = default !;
string _l_address2 = default !;
string _l_city = default !;
string _l_state = default !;
string _l_postalcode = default !;
string _l_name = default !;
string _l_phonenumber = default !;
string _l_country = default !;
ushort _r_assignedValid = 0b0;

var _l_serdeInfo = SerdeInfo;
var typeDeserialize = deserializer.ReadType(_l_serdeInfo);
int index;
while ((index = typeDeserialize.TryReadIndex(_l_serdeInfo, out _)) != IDeserializeType.EndOfType)
{
switch (index)
{
case 0:
_l_id = typeDeserialize.ReadI32(index);
_r_assignedValid |= ((ushort)1) << 0;
break;
case 1:
_l_address1 = typeDeserialize.ReadString(index);
_r_assignedValid |= ((ushort)1) << 1;
break;
case 2:
_l_address2 = typeDeserialize.ReadString(index);
_r_assignedValid |= ((ushort)1) << 2;
break;
case 3:
_l_city = typeDeserialize.ReadString(index);
_r_assignedValid |= ((ushort)1) << 3;
break;
case 4:
_l_state = typeDeserialize.ReadString(index);
_r_assignedValid |= ((ushort)1) << 4;
break;
case 5:
_l_postalcode = typeDeserialize.ReadString(index);
_r_assignedValid |= ((ushort)1) << 5;
break;
case 6:
_l_name = typeDeserialize.ReadString(index);
_r_assignedValid |= ((ushort)1) << 6;
break;
case 7:
_l_phonenumber = typeDeserialize.ReadString(index);
_r_assignedValid |= ((ushort)1) << 7;
break;
case 8:
_l_country = typeDeserialize.ReadString(index);
_r_assignedValid |= ((ushort)1) << 8;
break;
case Serde.IDeserializeType.IndexNotFound:
typeDeserialize.SkipValue();
break;
default:
throw new InvalidOperationException("Unexpected index: " + index);
}
}

if (_r_assignedValid != 0b111111111)
{
throw Serde.DeserializeException.UnassignedMember();
}

var newType = new Benchmarks.Location()
{
Id = _l_id,
Address1 = _l_address1,
Address2 = _l_address2,
City = _l_city,
State = _l_state,
PostalCode = _l_postalcode,
Name = _l_name,
PhoneNumber = _l_phonenumber,
Country = _l_country,
};
return newType;
}
}
}
34 changes: 34 additions & 0 deletions bench/SerializeToBytes.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using BenchmarkDotNet.Attributes;
using MessagePack;
using Serde;

namespace Benchmarks
{
[GenericTypeArguments(typeof(Location))]
public class SerializeToBytes<T>
where T : Serde.ISerializeProvider<T>
{
private T value = default!;

private readonly ISerialize<T> _proxy = T.Instance;

[GlobalSetup]
public void Setup()
{
value = DataGenerator.GenerateSerialize<T>();
}

[Benchmark]
public byte[] MessagePack()
{
return MessagePackSerializer.Serialize(value);
}

[Benchmark]
public byte[] SerdeMsgPack() => Serde.MsgPack.MsgPackSerializer.Serialize(value, _proxy);
}
}
20 changes: 10 additions & 10 deletions src/MsgPackSerializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,11 @@ public static class MsgPackSerializer
{
public static byte[] Serialize<T>(T value)
where T : ISerializeProvider<T>
{
using var buffer = new ScratchBuffer();
var writer = new MsgPackWriter(buffer);
var serializeObject = T.SerializeInstance;
serializeObject.Serialize(value, writer);
return buffer.Span.ToArray();
}
=> Serialize(value, T.Instance);

public static byte[] Serialize<T, U>(T value, U proxy)
where U : ISerialize<T>
public static byte[] Serialize<T>(T value, ISerialize<T> proxy)
{
using var buffer = new ScratchBuffer();
using var buffer = new ScratchBuffer(1024);
var writer = new MsgPackWriter(buffer);
proxy.Serialize(value, writer);
return buffer.Span.ToArray();
Expand All @@ -31,4 +24,11 @@ public static T Deserialize<T, U>(byte[] bytes, U proxy)
using var reader = new MsgPackReader<ArrayBufReader>(byteBuffer);
return proxy.Deserialize(reader);
}
public static T Deserialize<T>(byte[] bytes)
where T : IDeserializeProvider<T>
{
var byteBuffer = new ArrayBufReader(bytes);
using var reader = new MsgPackReader<ArrayBufReader>(byteBuffer);
return T.Instance.Deserialize(reader);
}
}
Loading