You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by pt...@apache.org on 2020/12/30 07:22:40 UTC
[ignite] branch master updated: IGNITE-13883 .NET: Simplify and
optimize TryReadSystemType
This is an automated email from the ASF dual-hosted git repository.
ptupitsyn pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 971f318 IGNITE-13883 .NET: Simplify and optimize TryReadSystemType
971f318 is described below
commit 971f31852a9fbdf14f0fd987d87d344b97298000
Author: Pavel Tupitsyn <pt...@apache.org>
AuthorDate: Wed Dec 30 10:22:08 2020 +0300
IGNITE-13883 .NET: Simplify and optimize TryReadSystemType
Replace dictionary+interfaces with a simple switch statement in `BinarySystemHandlers.TryReadSystemType`:
* Less code
* Simpler
* Faster
Benchmark added: `BinarySystemTypeReadBenchmark`; results on Core i7-9700K, Ubuntu 20.04, .NET Core 3.1:
```
| | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
|------- |---------:|----------:|----------:|-------:|------:|------:|----------:|
| Before | 1.080 us | 0.0030 us | 0.0025 us | 0.0725 | - | - | 456 B |
| After | 849.4 ns | 4.44 ns | 4.16 ns | 0.0725 | - | - | 456 B |
```
(~20% improvement)
---
.../Apache.Ignite.BenchmarkDotNet.csproj | 4 +
.../Apache.Ignite.BenchmarkDotNet.snk | Bin 0 -> 596 bytes
.../Binary/BinarySystemTypeReadBenchmark.cs | 124 +++++++
.../Apache.Ignite.BenchmarkDotNet/Program.cs | 4 +-
.../Apache.Ignite.Core.Tests/Services/Model.cs | 13 +-
.../Apache.Ignite.Core/Impl/Binary/BinaryReader.cs | 28 +-
.../Impl/Binary/BinarySystemHandlers.cs | 407 +++++++--------------
.../Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs | 56 ++-
.../Apache.Ignite.Core/Properties/AssemblyInfo.cs | 1 +
9 files changed, 337 insertions(+), 300 deletions(-)
diff --git a/modules/platforms/dotnet/Apache.Ignite.BenchmarkDotNet/Apache.Ignite.BenchmarkDotNet.csproj b/modules/platforms/dotnet/Apache.Ignite.BenchmarkDotNet/Apache.Ignite.BenchmarkDotNet.csproj
index 338ddd8..b2ff028 100644
--- a/modules/platforms/dotnet/Apache.Ignite.BenchmarkDotNet/Apache.Ignite.BenchmarkDotNet.csproj
+++ b/modules/platforms/dotnet/Apache.Ignite.BenchmarkDotNet/Apache.Ignite.BenchmarkDotNet.csproj
@@ -5,6 +5,10 @@
<TargetFramework>netcoreapp2.0</TargetFramework>
<ServerGarbageCollection>true</ServerGarbageCollection>
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
+ <AssemblyOriginatorKeyFile>Apache.Ignite.BenchmarkDotNet.snk</AssemblyOriginatorKeyFile>
+ <SignAssembly>true</SignAssembly>
+ <DelaySign>false</DelaySign>
+ <ServerGarbageCollection>true</ServerGarbageCollection>
</PropertyGroup>
<ItemGroup>
diff --git a/modules/platforms/dotnet/Apache.Ignite.BenchmarkDotNet/Apache.Ignite.BenchmarkDotNet.snk b/modules/platforms/dotnet/Apache.Ignite.BenchmarkDotNet/Apache.Ignite.BenchmarkDotNet.snk
new file mode 100644
index 0000000..886b6bb
Binary files /dev/null and b/modules/platforms/dotnet/Apache.Ignite.BenchmarkDotNet/Apache.Ignite.BenchmarkDotNet.snk differ
diff --git a/modules/platforms/dotnet/Apache.Ignite.BenchmarkDotNet/Binary/BinarySystemTypeReadBenchmark.cs b/modules/platforms/dotnet/Apache.Ignite.BenchmarkDotNet/Binary/BinarySystemTypeReadBenchmark.cs
new file mode 100644
index 0000000..c40b403
--- /dev/null
+++ b/modules/platforms/dotnet/Apache.Ignite.BenchmarkDotNet/Binary/BinarySystemTypeReadBenchmark.cs
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// ReSharper disable RedundantCast
+namespace Apache.Ignite.BenchmarkDotNet.Binary
+{
+ using System;
+ using System.IO;
+ using Apache.Ignite.Core.Binary;
+ using Apache.Ignite.Core.Impl.Binary;
+ using Apache.Ignite.Core.Impl.Memory;
+ using global::BenchmarkDotNet.Attributes;
+ using BinaryReader = Apache.Ignite.Core.Impl.Binary.BinaryReader;
+
+ /// <summary>
+ /// System type reading benchmark. Checks <see cref="BinarySystemHandlers.TryReadSystemType{T}"/> performance.
+ /// <para />
+ /// Results on Core i7-9700K, Ubuntu 20.04, .NET Core 3.1:
+ /// | Method | Mean | Error | StdDev | Gen 0 | Gen 1 | Gen 2 | Allocated |
+ /// |------- |---------:|--------:|--------:|-------:|------:|------:|----------:|
+ /// | Read | 849.4 ns | 4.44 ns | 4.16 ns | 0.0725 | - | - | 456 B |
+ /// </summary>
+ [MemoryDiagnoser]
+ public class BinarySystemTypeReadBenchmark
+ {
+ /** */
+ private static readonly DateTime DateTime = new DateTime(2010, 10, 10).ToUniversalTime();
+
+ /** */
+ private static readonly Guid Guid = Guid.NewGuid();
+
+ /** */
+ private static readonly Marshaller Marsh = new Marshaller(new BinaryConfiguration {ForceTimestamp = true});
+
+ /** */
+ private static readonly PlatformMemoryManager MemMgr = new PlatformMemoryManager(1024);
+
+ /** */
+ private BinaryReader _reader;
+
+ /// <summary>
+ /// Sets up the benchmark.
+ /// </summary>
+ [GlobalSetup]
+ public void Setup()
+ {
+ var mem = MemMgr.Allocate();
+ var stream = mem.GetStream();
+ var writer = Marsh.StartMarshal(stream);
+
+ writer.Write(true);
+ writer.Write('i');
+ writer.Write((byte) 1);
+ writer.Write((short) 2);
+ writer.Write((int) 3);
+ writer.Write((long) 4);
+ writer.Write((float) 5.5);
+ writer.Write((double) 6.6);
+ writer.Write((decimal) 7.7);
+ writer.Write(DateTime);
+ writer.Write(Guid);
+
+ writer.Write(new[] {true});
+ writer.Write(new[] {'i'});
+ writer.Write(new[] {(byte) 1});
+ writer.Write(new[] {(short) 2});
+ writer.Write(new[] {(int) 3});
+ writer.Write(new[] {(long) 4});
+ writer.Write(new[] {(float) 5.5});
+ writer.Write(new[] {(double) 6.6});
+ writer.Write(new[] {(decimal?) 7.7});
+ writer.Write(new DateTime?[] {DateTime});
+ writer.Write(new Guid?[] {Guid});
+
+ stream.SynchronizeOutput();
+
+ _reader = Marsh.StartUnmarshal(stream);
+ }
+
+ [Benchmark]
+ public void Read()
+ {
+ _reader.Stream.Seek(0, SeekOrigin.Begin);
+
+ _reader.ReadObject<bool>();
+ _reader.ReadObject<char>();
+ _reader.ReadObject<byte>();
+ _reader.ReadObject<short>();
+ _reader.ReadObject<int>();
+ _reader.ReadObject<long>();
+ _reader.ReadObject<float>();
+ _reader.ReadObject<double>();
+ _reader.ReadObject<decimal>();
+ _reader.ReadObject<DateTime>();
+ _reader.ReadObject<Guid>();
+
+ _reader.ReadObject<bool[]>();
+ _reader.ReadObject<char[]>();
+ _reader.ReadObject<byte[]>();
+ _reader.ReadObject<short[]>();
+ _reader.ReadObject<int[]>();
+ _reader.ReadObject<long[]>();
+ _reader.ReadObject<float[]>();
+ _reader.ReadObject<double[]>();
+ _reader.ReadObject<decimal?[]>();
+ _reader.ReadObject<DateTime?[]>();
+ _reader.ReadObject<Guid?[]>();
+ }
+ }
+}
diff --git a/modules/platforms/dotnet/Apache.Ignite.BenchmarkDotNet/Program.cs b/modules/platforms/dotnet/Apache.Ignite.BenchmarkDotNet/Program.cs
index d9f53d4..3a1513b 100644
--- a/modules/platforms/dotnet/Apache.Ignite.BenchmarkDotNet/Program.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.BenchmarkDotNet/Program.cs
@@ -17,7 +17,7 @@
namespace Apache.Ignite.BenchmarkDotNet
{
- using Apache.Ignite.BenchmarkDotNet.ThinClient;
+ using Apache.Ignite.BenchmarkDotNet.Binary;
using global::BenchmarkDotNet.Running;
/// <summary>
@@ -30,7 +30,7 @@ namespace Apache.Ignite.BenchmarkDotNet
/// </summary>
public static void Main()
{
- BenchmarkRunner.Run<ThinClientServicesBenchmark>();
+ BenchmarkRunner.Run<BinarySystemTypeReadBenchmark>();
}
}
}
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/Model.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/Model.cs
index e030098..e239c45 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/Model.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Services/Model.cs
@@ -94,7 +94,7 @@ namespace org.apache.ignite.platform.model
public class Account
{
public String Id { get; set; }
-
+
public int Amount { get; set; }
protected bool Equals(Account other)
@@ -120,6 +120,7 @@ namespace org.apache.ignite.platform.model
/// <summary>
/// A enum is a clone of Java class User with the same namespace.
/// </summary>
+ // ReSharper disable once InconsistentNaming
public enum ACL
{
Allow, Deny
@@ -139,16 +140,16 @@ namespace org.apache.ignite.platform.model
public class User
{
public int Id { get; set; }
-
+
public ACL Acl { get; set; }
-
+
public Role Role { get; set; }
- }
-
+ }
+
/// <summary>
/// A class is a clone of Java class ParamValue with the same namespace.
/// </summary>
- public class ParamValue
+ public class ParamValue
{
/** */
public int Id { get; set; }
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
index c1a6fed..2d266d6 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryReader.cs
@@ -29,7 +29,7 @@ namespace Apache.Ignite.Core.Impl.Binary
using Apache.Ignite.Core.Impl.Common;
/// <summary>
- /// Binary reader implementation.
+ /// Binary reader implementation.
/// </summary>
internal class BinaryReader : IBinaryReader, IBinaryRawReader
{
@@ -60,7 +60,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <param name="builder">Builder.</param>
public BinaryReader
(Marshaller marsh,
- IBinaryStream stream,
+ IBinaryStream stream,
BinaryMode mode,
BinaryObjectBuilder builder)
{
@@ -323,19 +323,19 @@ namespace Apache.Ignite.Core.Impl.Binary
{
return Read(stream => BinaryUtils.ReadTimestamp(stream, _marsh.TimestampConverter), BinaryTypeId.Timestamp);
}
-
+
/** <inheritdoc /> */
public DateTime?[] ReadTimestampArray(string fieldName)
{
return ReadField(fieldName, stream => BinaryUtils.ReadTimestampArray(stream, _marsh.TimestampConverter), BinaryTypeId.ArrayTimestamp);
}
-
+
/** <inheritdoc /> */
public DateTime?[] ReadTimestampArray()
{
return Read(stream => BinaryUtils.ReadTimestampArray(stream, _marsh.TimestampConverter), BinaryTypeId.ArrayTimestamp);
}
-
+
/** <inheritdoc /> */
public string ReadString(string fieldName)
{
@@ -351,13 +351,13 @@ namespace Apache.Ignite.Core.Impl.Binary
/** <inheritdoc /> */
public string[] ReadStringArray(string fieldName)
{
- return ReadField(fieldName, r => BinaryUtils.ReadArray<string>(r, false), BinaryTypeId.ArrayString);
+ return ReadField(fieldName, stream => BinaryUtils.ReadStringArray(stream), BinaryTypeId.ArrayString);
}
/** <inheritdoc /> */
public string[] ReadStringArray()
{
- return Read(r => BinaryUtils.ReadArray<string>(r, false), BinaryTypeId.ArrayString);
+ return Read(stream => BinaryUtils.ReadStringArray(stream), BinaryTypeId.ArrayString);
}
/** <inheritdoc /> */
@@ -375,13 +375,13 @@ namespace Apache.Ignite.Core.Impl.Binary
/** <inheritdoc /> */
public Guid?[] ReadGuidArray(string fieldName)
{
- return ReadField(fieldName, r => BinaryUtils.ReadArray<Guid?>(r, false), BinaryTypeId.ArrayGuid);
+ return ReadField(fieldName, stream => BinaryUtils.ReadGuidArray(stream), BinaryTypeId.ArrayGuid);
}
/** <inheritdoc /> */
public Guid?[] ReadGuidArray()
{
- return Read(r => BinaryUtils.ReadArray<Guid?>(r, false), BinaryTypeId.ArrayGuid);
+ return Read(stream => BinaryUtils.ReadGuidArray(stream), BinaryTypeId.ArrayGuid);
}
/** <inheritdoc /> */
@@ -410,7 +410,7 @@ namespace Apache.Ignite.Core.Impl.Binary
// Unregistered enum written as serializable
Stream.Seek(-1, SeekOrigin.Current);
- return ReadObject<T>();
+ return ReadObject<T>();
default:
throw new BinaryObjectException(string.Format(
@@ -474,7 +474,7 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/** <inheritdoc /> */
- public ICollection ReadCollection(string fieldName, Func<int, ICollection> factory,
+ public ICollection ReadCollection(string fieldName, Func<int, ICollection> factory,
Action<ICollection, object> adder)
{
return ReadField(fieldName, r => BinaryUtils.ReadCollection(r, factory, adder), BinaryTypeId.Collection);
@@ -511,7 +511,7 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
- /// Enable detach mode for the next object read.
+ /// Enable detach mode for the next object read.
/// </summary>
public BinaryReader DetachNext()
{
@@ -800,7 +800,7 @@ namespace Apache.Ignite.Core.Impl.Binary
if (_frame.Schema == null)
{
- _frame.Schema =
+ _frame.Schema =
BinaryObjectSchemaSerializer.GetFieldIds(_frame.Hdr, Marshaller.Ignite, Stream, _frame.Pos);
desc.Schema.Add(_frame.Hdr.SchemaId, _frame.Schema);
@@ -889,7 +889,7 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
- /// Mark current output as raw.
+ /// Mark current output as raw.
/// </summary>
private void MarkRaw()
{
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
index 8fdf371..58a4d24 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinarySystemHandlers.cs
@@ -20,8 +20,6 @@ namespace Apache.Ignite.Core.Impl.Binary
using System;
using System.Collections;
using System.Diagnostics;
- using System.Diagnostics.CodeAnalysis;
- using Apache.Ignite.Core.Impl.Binary.IO;
using Apache.Ignite.Core.Impl.Common;
/**
@@ -33,83 +31,13 @@ namespace Apache.Ignite.Core.Impl.Binary
private static readonly CopyOnWriteConcurrentDictionary<Type, IBinarySystemWriteHandler> WriteHandlers =
new CopyOnWriteConcurrentDictionary<Type, IBinarySystemWriteHandler>();
- /** Read handlers. */
- private static readonly IBinarySystemReader[] ReadHandlers = new IBinarySystemReader[255];
-
- /// <summary>
- /// Initializes the <see cref="BinarySystemHandlers"/> class.
- /// </summary>
- [SuppressMessage("Microsoft.Performance", "CA1810:InitializeReferenceTypeStaticFieldsInline",
- Justification = "Readability.")]
- static BinarySystemHandlers()
- {
- // 1. Primitives.
- ReadHandlers[BinaryTypeId.Bool] = new BinarySystemReader<bool>(s => s.ReadBool());
- ReadHandlers[BinaryTypeId.Byte] = new BinarySystemReader<byte>(s => s.ReadByte());
- ReadHandlers[BinaryTypeId.Short] = new BinarySystemReader<short>(s => s.ReadShort());
- ReadHandlers[BinaryTypeId.Char] = new BinarySystemReader<char>(s => s.ReadChar());
- ReadHandlers[BinaryTypeId.Int] = new BinarySystemReader<int>(s => s.ReadInt());
- ReadHandlers[BinaryTypeId.Long] = new BinarySystemReader<long>(s => s.ReadLong());
- ReadHandlers[BinaryTypeId.Float] = new BinarySystemReader<float>(s => s.ReadFloat());
- ReadHandlers[BinaryTypeId.Double] = new BinarySystemReader<double>(s => s.ReadDouble());
- ReadHandlers[BinaryTypeId.Decimal] = new BinarySystemReader<decimal?>(BinaryUtils.ReadDecimal);
-
- // 3. String.
- ReadHandlers[BinaryTypeId.String] = new BinarySystemReader<string>(BinaryUtils.ReadString);
-
- // 4. Guid.
- ReadHandlers[BinaryTypeId.Guid] = new BinarySystemReader<Guid?>(s => BinaryUtils.ReadGuid(s));
-
- // 5. Primitive arrays.
- ReadHandlers[BinaryTypeId.ArrayBool] = new BinarySystemReader<bool[]>(BinaryUtils.ReadBooleanArray);
-
- ReadHandlers[BinaryTypeId.ArrayByte] =
- new BinarySystemDualReader<byte[], sbyte[]>(BinaryUtils.ReadByteArray, BinaryUtils.ReadSbyteArray);
-
- ReadHandlers[BinaryTypeId.ArrayShort] =
- new BinarySystemDualReader<short[], ushort[]>(BinaryUtils.ReadShortArray,
- BinaryUtils.ReadUshortArray);
-
- ReadHandlers[BinaryTypeId.ArrayChar] =
- new BinarySystemReader<char[]>(BinaryUtils.ReadCharArray);
-
- ReadHandlers[BinaryTypeId.ArrayInt] =
- new BinarySystemDualReader<int[], uint[]>(BinaryUtils.ReadIntArray, BinaryUtils.ReadUintArray);
-
- ReadHandlers[BinaryTypeId.ArrayLong] =
- new BinarySystemDualReader<long[], ulong[]>(BinaryUtils.ReadLongArray,
- BinaryUtils.ReadUlongArray);
-
- ReadHandlers[BinaryTypeId.ArrayFloat] =
- new BinarySystemReader<float[]>(BinaryUtils.ReadFloatArray);
-
- ReadHandlers[BinaryTypeId.ArrayDouble] =
- new BinarySystemReader<double[]>(BinaryUtils.ReadDoubleArray);
-
- ReadHandlers[BinaryTypeId.ArrayDecimal] =
- new BinarySystemReader<decimal?[]>(BinaryUtils.ReadDecimalArray);
-
- // 7. String array.
- ReadHandlers[BinaryTypeId.ArrayString] = new BinarySystemTypedArrayReader<string>();
-
- // 8. Guid array.
- ReadHandlers[BinaryTypeId.ArrayGuid] = new BinarySystemTypedArrayReader<Guid?>();
-
- // 9. Array.
- ReadHandlers[BinaryTypeId.Array] = new BinarySystemReader(ReadArray);
-
- // 11. Arbitrary collection.
- ReadHandlers[BinaryTypeId.Collection] = new BinarySystemReader(ReadCollection);
-
- // 13. Arbitrary dictionary.
- ReadHandlers[BinaryTypeId.Dictionary] = new BinarySystemReader(ReadDictionary);
-
- // 14. Enum. Should be read as Array, see WriteEnumArray implementation.
- ReadHandlers[BinaryTypeId.ArrayEnum] = new BinarySystemReader(ReadArray);
+ /** */
+ private static readonly BinarySystemWriteHandler<DateTime> TimestampWriteHandler =
+ new BinarySystemWriteHandler<DateTime>(WriteTimestamp, false);
- // 15. Optimized marshaller objects.
- ReadHandlers[BinaryTypeId.OptimizedMarshaller] = new BinarySystemReader(ReadOptimizedMarshallerObject);
- }
+ /** */
+ private static readonly BinarySystemWriteHandler<DateTime?[]> TimestampArrayWriteHandler =
+ new BinarySystemWriteHandler<DateTime?[]>(WriteTimestampArray, true);
/// <summary>
/// Try getting write handler for type.
@@ -122,9 +50,10 @@ namespace Apache.Ignite.Core.Impl.Binary
if (forceTimestamp)
{
if (type == typeof(DateTime))
- return new BinarySystemWriteHandler<DateTime>(WriteTimestamp, false);
+ return TimestampWriteHandler;
+
if (type == typeof(DateTime?[]))
- return new BinarySystemWriteHandler<DateTime?[]>(WriteTimestampArray, true);
+ return TimestampArrayWriteHandler;
}
return WriteHandlers.GetOrAdd(type, t =>
@@ -192,7 +121,7 @@ namespace Apache.Ignite.Core.Impl.Binary
// We know how to write any array type.
Type elemType = type.GetElementType();
-
+
// Primitives.
if (elemType == typeof (bool))
return new BinarySystemWriteHandler<bool[]>(WriteBoolArray, true);
@@ -247,32 +176,139 @@ namespace Apache.Ignite.Core.Impl.Binary
/// </summary>
public static bool TryReadSystemType<T>(byte typeId, BinaryReader ctx, out T res)
{
- var handler = ReadHandlers[typeId];
+ var stream = ctx.Stream;
- if (handler == null)
+ switch (typeId)
{
- if (typeId == BinaryTypeId.Timestamp)
- {
- // Date.
- res = TypeCaster<T>.Cast(BinaryUtils.ReadTimestamp(ctx.Stream, ctx.Marshaller.TimestampConverter));
+ case BinaryTypeId.Byte:
+ res = TypeCaster<T>.Cast(stream.ReadByte());
return true;
- }
- if (typeId == BinaryTypeId.ArrayTimestamp)
- {
- // Date array.
- res = TypeCaster<T>.Cast(BinaryUtils.ReadTimestampArray(ctx.Stream, ctx.Marshaller.TimestampConverter));
+ case BinaryTypeId.Short:
+ res = TypeCaster<T>.Cast(stream.ReadShort());
+ return true;
+
+ case BinaryTypeId.Int:
+ res = TypeCaster<T>.Cast(stream.ReadInt());
+ return true;
+
+ case BinaryTypeId.Long:
+ res = TypeCaster<T>.Cast(stream.ReadLong());
+ return true;
+
+ case BinaryTypeId.Float:
+ res = TypeCaster<T>.Cast(stream.ReadFloat());
+ return true;
+
+ case BinaryTypeId.Double:
+ res = TypeCaster<T>.Cast(stream.ReadDouble());
+ return true;
+
+ case BinaryTypeId.Char:
+ res = TypeCaster<T>.Cast(stream.ReadChar());
+ return true;
+
+ case BinaryTypeId.Bool:
+ res = TypeCaster<T>.Cast(stream.ReadBool());
+ return true;
+
+ case BinaryTypeId.String:
+ res = TypeCaster<T>.Cast(BinaryUtils.ReadString(stream));
+ return true;
+
+ case BinaryTypeId.Guid:
+ res = TypeCaster<T>.Cast(BinaryUtils.ReadGuid(stream));
+ return true;
+
+ case BinaryTypeId.ArrayByte:
+ res = typeof(T) == typeof(sbyte[])
+ ? TypeCaster<T>.Cast(BinaryUtils.ReadSbyteArray(stream))
+ : TypeCaster<T>.Cast(BinaryUtils.ReadByteArray(stream));
+ return true;
+
+ case BinaryTypeId.ArrayShort:
+ res = typeof(T) == typeof(ushort[])
+ ? TypeCaster<T>.Cast(BinaryUtils.ReadUshortArray(stream))
+ : TypeCaster<T>.Cast(BinaryUtils.ReadShortArray(stream));
+ return true;
+
+ case BinaryTypeId.ArrayInt:
+ res = typeof(T) == typeof(uint[])
+ ? TypeCaster<T>.Cast(BinaryUtils.ReadUintArray(stream))
+ : TypeCaster<T>.Cast(BinaryUtils.ReadIntArray(stream));
+ return true;
+
+ case BinaryTypeId.ArrayLong:
+ res = typeof(T) == typeof(ulong[])
+ ? TypeCaster<T>.Cast(BinaryUtils.ReadUlongArray(stream))
+ : TypeCaster<T>.Cast(BinaryUtils.ReadLongArray(stream));
+ return true;
+
+ case BinaryTypeId.ArrayFloat:
+ res = TypeCaster<T>.Cast(BinaryUtils.ReadFloatArray(stream));
+ return true;
+
+ case BinaryTypeId.ArrayDouble:
+ res = TypeCaster<T>.Cast(BinaryUtils.ReadDoubleArray(stream));
+ return true;
+
+ case BinaryTypeId.ArrayChar:
+ res = TypeCaster<T>.Cast(BinaryUtils.ReadCharArray(stream));
+ return true;
+
+ case BinaryTypeId.ArrayBool:
+ res = TypeCaster<T>.Cast(BinaryUtils.ReadBooleanArray(stream));
+ return true;
+
+ case BinaryTypeId.ArrayString:
+ res = TypeCaster<T>.Cast(BinaryUtils.ReadStringArray(stream));
+ return true;
+
+ case BinaryTypeId.ArrayGuid:
+ res = TypeCaster<T>.Cast(BinaryUtils.ReadGuidArray(stream));
+ return true;
+
+ case BinaryTypeId.Array:
+ res = (T) ReadArray(ctx, typeof(T));
+ return true;
+
+ case BinaryTypeId.Collection:
+ res = (T) BinaryUtils.ReadCollection(ctx, null, null);
+ return true;
+
+ case BinaryTypeId.Dictionary:
+ res = (T) BinaryUtils.ReadDictionary(ctx, null);
+ return true;
+
+ case BinaryTypeId.ArrayEnum:
+ res = (T) ReadArray(ctx, typeof(T));
+ return true;
+
+ case BinaryTypeId.Decimal:
+ res = TypeCaster<T>.Cast(BinaryUtils.ReadDecimal(stream));
+ return true;
+
+ case BinaryTypeId.ArrayDecimal:
+ res = TypeCaster<T>.Cast(BinaryUtils.ReadDecimalArray(stream));
+ return true;
+
+ case BinaryTypeId.Timestamp:
+ res = TypeCaster<T>.Cast(BinaryUtils.ReadTimestamp(stream, ctx.Marshaller.TimestampConverter));
+ return true;
+
+ case BinaryTypeId.ArrayTimestamp:
+ res = TypeCaster<T>.Cast(BinaryUtils.ReadTimestampArray(stream, ctx.Marshaller.TimestampConverter));
return true;
- }
- res = default(T);
- return false;
+ case BinaryTypeId.OptimizedMarshaller:
+ res = (T) (object) new OptimizedMarshallerObject(ctx.Stream);
+ return true;
}
- res = handler.Read<T>(ctx);
- return true;
+ res = default(T);
+ return false;
}
-
+
/// <summary>
/// Write decimal.
/// </summary>
@@ -284,7 +320,7 @@ namespace Apache.Ignite.Core.Impl.Binary
BinaryUtils.WriteDecimal(obj, ctx.Stream);
}
-
+
/// <summary>
/// Write string.
/// </summary>
@@ -332,7 +368,7 @@ namespace Apache.Ignite.Core.Impl.Binary
BinaryUtils.WriteBooleanArray(obj, ctx.Stream);
}
-
+
/// <summary>
/// Write byte array.
/// </summary>
@@ -356,7 +392,7 @@ namespace Apache.Ignite.Core.Impl.Binary
BinaryUtils.WriteShortArray(obj, ctx.Stream);
}
-
+
/// <summary>
/// Write char array.
/// </summary>
@@ -428,7 +464,7 @@ namespace Apache.Ignite.Core.Impl.Binary
BinaryUtils.WriteDecimalArray(obj, ctx.Stream);
}
-
+
/// <summary>
/// Write string array.
/// </summary>
@@ -440,7 +476,7 @@ namespace Apache.Ignite.Core.Impl.Binary
BinaryUtils.WriteStringArray(obj, ctx.Stream);
}
-
+
/// <summary>
/// Write nullable GUID array.
/// </summary>
@@ -514,7 +550,7 @@ namespace Apache.Ignite.Core.Impl.Binary
BinaryUtils.WriteBinary(ctx.Stream, obj);
}
-
+
/// <summary>
/// Write enum.
/// </summary>
@@ -557,22 +593,6 @@ namespace Apache.Ignite.Core.Impl.Binary
return BinaryUtils.ReadTypedArray(ctx, true, elemType);
}
- /**
- * <summary>Read collection.</summary>
- */
- private static object ReadCollection(BinaryReader ctx, Type type)
- {
- return BinaryUtils.ReadCollection(ctx, null, null);
- }
-
- /**
- * <summary>Read dictionary.</summary>
- */
- private static object ReadDictionary(BinaryReader ctx, Type type)
- {
- return BinaryUtils.ReadDictionary(ctx, null);
- }
-
/// <summary>
/// Write Ignite.
/// </summary>
@@ -580,151 +600,6 @@ namespace Apache.Ignite.Core.Impl.Binary
{
ctx.Stream.WriteByte(BinaryUtils.HdrNull);
}
-
- /// <summary>
- /// Reads the optimized marshaller object.
- /// </summary>
- private static object ReadOptimizedMarshallerObject(BinaryReader ctx, Type type)
- {
- return new OptimizedMarshallerObject(ctx.Stream);
- }
-
- /**
- * <summary>Read delegate.</summary>
- * <param name="ctx">Read context.</param>
- * <param name="type">Type.</param>
- */
- private delegate object BinarySystemReadDelegate(BinaryReader ctx, Type type);
-
- /// <summary>
- /// System type reader.
- /// </summary>
- private interface IBinarySystemReader
- {
- /// <summary>
- /// Reads a value of specified type from reader.
- /// </summary>
- T Read<T>(BinaryReader ctx);
- }
-
- /// <summary>
- /// System type generic reader.
- /// </summary>
- private interface IBinarySystemReader<out T>
- {
- /// <summary>
- /// Reads a value of specified type from reader.
- /// </summary>
- T Read(BinaryReader ctx);
- }
-
- /// <summary>
- /// Default reader with boxing.
- /// </summary>
- private class BinarySystemReader : IBinarySystemReader
- {
- /** */
- private readonly BinarySystemReadDelegate _readDelegate;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="BinarySystemReader"/> class.
- /// </summary>
- /// <param name="readDelegate">The read delegate.</param>
- public BinarySystemReader(BinarySystemReadDelegate readDelegate)
- {
- Debug.Assert(readDelegate != null);
-
- _readDelegate = readDelegate;
- }
-
- /** <inheritdoc /> */
- public T Read<T>(BinaryReader ctx)
- {
- return (T)_readDelegate(ctx, typeof(T));
- }
- }
-
- /// <summary>
- /// Reader without boxing.
- /// </summary>
- private class BinarySystemReader<T> : IBinarySystemReader
- {
- /** */
- private readonly Func<IBinaryStream, T> _readDelegate;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="BinarySystemReader{T}"/> class.
- /// </summary>
- /// <param name="readDelegate">The read delegate.</param>
- public BinarySystemReader(Func<IBinaryStream, T> readDelegate)
- {
- Debug.Assert(readDelegate != null);
-
- _readDelegate = readDelegate;
- }
-
- /** <inheritdoc /> */
- public TResult Read<TResult>(BinaryReader ctx)
- {
- return TypeCaster<TResult>.Cast(_readDelegate(ctx.Stream));
- }
- }
-
- /// <summary>
- /// Reader without boxing.
- /// </summary>
- private class BinarySystemTypedArrayReader<T> : IBinarySystemReader
- {
- public TResult Read<TResult>(BinaryReader ctx)
- {
- return TypeCaster<TResult>.Cast(BinaryUtils.ReadArray<T>(ctx, false));
- }
- }
-
- /// <summary>
- /// Reader with selection based on requested type.
- /// </summary>
- private class BinarySystemDualReader<T1, T2> : IBinarySystemReader, IBinarySystemReader<T2>
- {
- /** */
- private readonly Func<IBinaryStream, T1> _readDelegate1;
-
- /** */
- private readonly Func<IBinaryStream, T2> _readDelegate2;
-
- /// <summary>
- /// Initializes a new instance of the <see cref="BinarySystemDualReader{T1,T2}"/> class.
- /// </summary>
- /// <param name="readDelegate1">The read delegate1.</param>
- /// <param name="readDelegate2">The read delegate2.</param>
- public BinarySystemDualReader(Func<IBinaryStream, T1> readDelegate1, Func<IBinaryStream, T2> readDelegate2)
- {
- Debug.Assert(readDelegate1 != null);
- Debug.Assert(readDelegate2 != null);
-
- _readDelegate1 = readDelegate1;
- _readDelegate2 = readDelegate2;
- }
-
- /** <inheritdoc /> */
- [SuppressMessage("Microsoft.Design", "CA1062:Validate arguments of public methods")]
- T2 IBinarySystemReader<T2>.Read(BinaryReader ctx)
- {
- return _readDelegate2(ctx.Stream);
- }
-
- /** <inheritdoc /> */
- public T Read<T>(BinaryReader ctx)
- {
- // Can't use "as" because of variance.
- // For example, IBinarySystemReader<byte[]> can be cast to IBinarySystemReader<sbyte[]>, which
- // will cause incorrect behavior.
- if (typeof (T) == typeof (T2))
- return ((IBinarySystemReader<T>) this).Read(ctx);
-
- return TypeCaster<T>.Cast(_readDelegate1(ctx.Stream));
- }
- }
}
/// <summary>
@@ -748,7 +623,7 @@ namespace Apache.Ignite.Core.Impl.Binary
/// <summary>
/// Write delegate + handles flag.
/// </summary>
- internal class BinarySystemWriteHandler<T1> : IBinarySystemWriteHandler
+ internal sealed class BinarySystemWriteHandler<T1> : IBinarySystemWriteHandler
{
/** */
private readonly Action<BinaryWriter, T1> _writeAction;
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
index 82e2284..a60411f 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Binary/BinaryUtils.cs
@@ -110,9 +110,9 @@ namespace Apache.Ignite.Core.Impl.Binary
/** String mode. */
public static readonly bool UseStringSerializationVer2 =
(Environment.GetEnvironmentVariable(IgniteBinaryMarshallerUseStringSerializationVer2) ?? "false") == "true";
-
+
/** Cached maps of enum members per type. */
- private static readonly CopyOnWriteConcurrentDictionary<Type, Dictionary<string, int>> EnumValues =
+ private static readonly CopyOnWriteConcurrentDictionary<Type, Dictionary<string, int>> EnumValues =
new CopyOnWriteConcurrentDictionary<Type, Dictionary<string, int>>();
/// <summary>
@@ -926,7 +926,7 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
- /// Writes a guid with bitwise conversion, assuming that <see cref="Guid"/>
+ /// Writes a guid with bitwise conversion, assuming that <see cref="Guid"/>
/// is laid out in memory sequentially and without gaps between fields.
/// </summary>
/// <param name="val">The value.</param>
@@ -974,7 +974,7 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
- /// Reads a guid with bitwise conversion, assuming that <see cref="Guid"/>
+ /// Reads a guid with bitwise conversion, assuming that <see cref="Guid"/>
/// is laid out in memory sequentially and without gaps between fields.
/// </summary>
/// <param name="stream">The stream.</param>
@@ -1103,8 +1103,8 @@ namespace Apache.Ignite.Core.Impl.Binary
/// </summary>
public static int GetArrayElementTypeId(Type elemType, Marshaller marsh)
{
- return elemType == typeof(object)
- ? ObjTypeId
+ return elemType == typeof(object)
+ ? ObjTypeId
: marsh.GetDescriptor(elemType).TypeId;
}
@@ -1171,6 +1171,38 @@ namespace Apache.Ignite.Core.Impl.Binary
}
/// <summary>
+ /// Read string array.
+ /// </summary>
+ /// <param name="stream">Stream</param>
+ /// <returns>String array.</returns>
+ public static string[] ReadStringArray(IBinaryStream stream)
+ {
+ var len = stream.ReadInt();
+ var res = new string[len];
+
+ for (var i = 0; i < len; i++)
+ res[i] = stream.ReadByte() == HdrNull ? null : ReadString(stream);
+
+ return res;
+ }
+
+ /// <summary>
+ /// Read string array.
+ /// </summary>
+ /// <param name="stream">Stream</param>
+ /// <returns>String array.</returns>
+ public static Guid?[] ReadGuidArray(IBinaryStream stream)
+ {
+ var len = stream.ReadInt();
+ var res = new Guid?[len];
+
+ for (var i = 0; i < len; i++)
+ res[i] = stream.ReadByte() == HdrNull ? (Guid?) null : ReadGuid(stream);
+
+ return res;
+ }
+
+ /// <summary>
/// Read timestamp array.
/// </summary>
/// <param name="stream">Stream.</param>
@@ -1596,7 +1628,7 @@ namespace Apache.Ignite.Core.Impl.Binary
err = null;
if (reader.ReadBoolean()) // success indication
- return reader.ReadObject<object>();
+ return reader.ReadObject<object>();
err = reader.ReadBoolean() // native error indication
? reader.ReadObject<object>()
@@ -1746,7 +1778,7 @@ namespace Apache.Ignite.Core.Impl.Binary
var enumType = Enum.GetUnderlyingType(type);
- return enumType == typeof(int) || enumType == typeof(byte) || enumType == typeof(sbyte)
+ return enumType == typeof(int) || enumType == typeof(byte) || enumType == typeof(sbyte)
|| enumType == typeof(short) || enumType == typeof(ushort) || enumType == typeof(uint);
}
@@ -1763,7 +1795,7 @@ namespace Apache.Ignite.Core.Impl.Binary
return TimeSpan.FromMilliseconds(ms);
}
-
+
/// <summary>
/// Gets the enum values.
/// </summary>
@@ -1771,7 +1803,7 @@ namespace Apache.Ignite.Core.Impl.Binary
{
Debug.Assert(enumType != null);
Debug.Assert(enumType.IsEnum);
-
+
Dictionary<string,int> res;
if (EnumValues.TryGetValue(enumType, out res))
{
@@ -1792,10 +1824,10 @@ namespace Apache.Ignite.Core.Impl.Binary
}
EnumValues.Set(enumType, res);
-
+
return res;
}
-
+
/// <summary>
/// Gets the enum value as int.
/// </summary>
diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Properties/AssemblyInfo.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Properties/AssemblyInfo.cs
index 608a527..63b7ee3 100644
--- a/modules/platforms/dotnet/Apache.Ignite.Core/Properties/AssemblyInfo.cs
+++ b/modules/platforms/dotnet/Apache.Ignite.Core/Properties/AssemblyInfo.cs
@@ -48,5 +48,6 @@ using System.Runtime.InteropServices;
[assembly: InternalsVisibleTo("Apache.Ignite, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e3e6312f7ca1ab31b8ac8408668fc85b4a76a689f7eef8553d491a594cd9ea29432b7aea12ed8f34925b2db1e01fa64f333c4e8866252a2b2d512afa5d2e06eef94fb2cdd05904f2ad70d3752fbf531bef128ecad9e699f54b2cfcd0b394b7b40e33b8c7ed45a2cd300e1b4d01c8ec7fd753683594a18f396727c304920a5e97")]
#if NETCOREAPP
[assembly: InternalsVisibleTo("Apache.Ignite.Core.Tests.DotNetCore, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c9b65cf83e050e9d360a840fc6632774936ea62a9a14db0aa1b991ac6b7c94030a647be9755d6b3b5883367c58cb834866b4f3acbdb5881dff677f2c046ed7cae85c9a62a7737f377813ebe4ae19f89d357e811aa577c909b82d5f02a9b05dab39da3ff92927ce0b0c4d0204961ee5d5c329274b68f19ebba129ee8e3fd0d0c1")]
+[assembly: InternalsVisibleTo("Apache.Ignite.BenchmarkDotNet, PublicKey=0024000004800000940000000602000000240000525341310004000001000100a3e0c1df4cbedbd4ed0e88808401c69b69ec12575ed1c056ac9f448e018fb29af19d236b7b03563aad66c48ab2045e72971ed098d4f65d4cdd38d65abcb39b4f84c626b22ccab2754375f0e8c97dc304fa146f0eddad5cc40a71803a8f15b0b0bb0bff0d4bf0ff6a64bb1044e0d71e6e2405b83fd4c1f7b3e2cfc2e9d50823d4")]
#endif
#endif