Repository: ignite Updated Branches: refs/heads/ignite-1770 8e5ca8404 -> 85064003d
IGNITE-1770: Optimized read perf for .Net. Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/85064003 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/85064003 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/85064003 Branch: refs/heads/ignite-1770 Commit: 85064003d8c6810ecd42ac58a52c40ff0cdc9ab9 Parents: 8e5ca84 Author: vozerov-gridgain <[email protected]> Authored: Fri Oct 30 11:58:23 2015 +0300 Committer: vozerov-gridgain <[email protected]> Committed: Fri Oct 30 11:58:23 2015 +0300 ---------------------------------------------------------------------- .../Apache.Ignite.Benchmarks/BenchmarkRunner.cs | 2 +- .../Apache.Ignite.Core.csproj | 1 + .../Impl/Portable/IPortableTypeDescriptor.cs | 5 + .../Impl/Portable/PortableFullTypeDescriptor.cs | 9 ++ .../Impl/Portable/PortableObjectSchema.cs | 98 ++++++++++++++++++++ .../Impl/Portable/PortableObjectSchemaField.cs | 3 + .../Impl/Portable/PortableReaderImpl.cs | 46 ++++++++- .../Portable/PortableSurrogateTypeDescriptor.cs | 9 ++ .../Structure/PortableStructureTracker.cs | 8 ++ 9 files changed, 178 insertions(+), 3 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/85064003/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs index 506106e..2d0d348 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Benchmarks/BenchmarkRunner.cs @@ -35,7 +35,7 @@ namespace Apache.Ignite.Benchmarks public static void Main(string[] args) { args = new[] { - typeof(PortableWriteBenchmark).FullName, + typeof(PortableReadBenchmark).FullName, "-ConfigPath", @"modules\platforms\dotnet\Apache.Ignite.Benchmarks\Config\benchmark.xml", "-Threads", "1", "-Warmup", "0", http://git-wip-us.apache.org/repos/asf/ignite/blob/85064003/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj index 9f2c6bd..ffe5d9f 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Apache.Ignite.Core.csproj @@ -256,6 +256,7 @@ <Compile Include="Impl\Portable\PortableMode.cs" /> <Compile Include="Impl\Portable\PortableObjectHandle.cs" /> <Compile Include="Impl\Portable\PortableObjectHeader.cs" /> + <Compile Include="Impl\Portable\PortableObjectSchema.cs" /> <Compile Include="Impl\Portable\PortableObjectSchemaField.cs" /> <Compile Include="Impl\Portable\PortableReaderExtensions.cs" /> <Compile Include="Impl\Portable\PortableReaderHandleDictionary.cs" /> http://git-wip-us.apache.org/repos/asf/ignite/blob/85064003/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableTypeDescriptor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableTypeDescriptor.cs index 3872773..88a7e22 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/IPortableTypeDescriptor.cs @@ -133,5 +133,10 @@ namespace Apache.Ignite.Core.Impl.Portable /// <param name="pathIdx">Path index.</param> /// <param name="updates">Recorded updates.</param> void UpdateReadStructure(PortableStructure exp, int pathIdx, IList<PortableStructureUpdate> updates); + + /// <summary> + /// Gets the schema. + /// </summary> + PortableObjectSchema Schema { get; } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/85064003/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableFullTypeDescriptor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableFullTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableFullTypeDescriptor.cs index 312cefa..8695a3e 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableFullTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableFullTypeDescriptor.cs @@ -63,6 +63,9 @@ namespace Apache.Ignite.Core.Impl.Portable /** Type structure. */ private volatile PortableStructure _readerTypeStructure = PortableStructure.CreateEmpty(); + + /** Type schema. */ + private readonly PortableObjectSchema _schema = new PortableObjectSchema(); /// <summary> /// Constructor. @@ -212,5 +215,11 @@ namespace Apache.Ignite.Core.Impl.Portable _readerTypeStructure = _readerTypeStructure.Merge(exp, pathIdx, updates); } } + + /** <inheritDoc /> */ + public PortableObjectSchema Schema + { + get { return _schema; } + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/85064003/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableObjectSchema.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableObjectSchema.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableObjectSchema.cs new file mode 100644 index 0000000..7d3663c --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableObjectSchema.cs @@ -0,0 +1,98 @@ +/* + * 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. + */ + +namespace Apache.Ignite.Core.Impl.Portable +{ + using System.Collections.Generic; + + /// <summary> + /// Holds and manages portable object schema for a specific type. + /// </summary> + internal class PortableObjectSchema + { + /** First schema id. */ + private volatile int _schemaId1; + + /** First schema. */ + private volatile int[] _schema1; + + /** Second schema id. */ + private volatile int _schemaId2; + + /** Second schema. */ + private volatile int[] _schema2; + + /** Other schemas. */ + private volatile Dictionary<int, int[]> _schemas; + + /// <summary> + /// Gets the schema by id. + /// </summary> + /// <param name="id">Schema id.</param> + /// <returns>Schema or null.</returns> + public int[] GetSchema(int id) + { + if (_schemaId1 == id) + return _schema1; + + if (_schemaId2 == id) + return _schema2; + + int[] res; + + if (_schemas != null && _schemas.TryGetValue(id, out res)) + return res; + + return null; + } + + /// <summary> + /// Adds the schema. + /// </summary> + /// <param name="id">Schema id.</param> + /// <param name="schema">Schema.</param> + public void AddSchema(int id, int[] schema) + { + lock (this) + { + if (_schemaId1 == id || _schemaId2 == id || (_schemas != null && _schemas.ContainsKey(id))) + return; + + if (_schema1 == null) + { + _schemaId1 = id; + _schema1 = schema; + } + else if (_schema2 == null) + { + _schemaId2 = id; + _schema2 = schema; + } + else + { + var schemas = _schemas == null + ? new Dictionary<int, int[]>() + : new Dictionary<int, int[]>(_schemas); + + schemas.Add(id, schema); + + _schemas = schemas; + } + } + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/85064003/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableObjectSchemaField.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableObjectSchemaField.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableObjectSchemaField.cs index 5d489c3..48fd9c1 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableObjectSchemaField.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableObjectSchemaField.cs @@ -22,6 +22,9 @@ namespace Apache.Ignite.Core.Impl.Portable using System.Runtime.InteropServices; using Apache.Ignite.Core.Impl.Portable.IO; + /// <summary> + /// Portable schema field DTO (as it is stored in a stream). + /// </summary> [StructLayout(LayoutKind.Sequential)] internal struct PortableObjectSchemaField { http://git-wip-us.apache.org/repos/asf/ignite/blob/85064003/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs index a289816..48ea799 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableReaderImpl.cs @@ -72,6 +72,8 @@ namespace Apache.Ignite.Core.Impl.Portable /** */ private int _curFooterEnd; + /** */ + private int[] _curSchema; /// <summary> /// Constructor. @@ -674,12 +676,23 @@ namespace Apache.Ignite.Core.Impl.Portable bool oldRaw = _curRaw; var oldFooterStart = _curFooterStart; var oldFooterEnd = _curFooterEnd; + var oldSchema = _curSchema; // Set new frame. _curTypeId = hdr.TypeId; _curPos = pos; _curFooterEnd = hdr.GetSchemaEnd(pos); _curFooterStart = hdr.GetSchemaStart(pos); + + _curSchema = desc.Schema.GetSchema(hdr.SchemaId); + + if (_curSchema == null) + { + _curSchema = ReadSchema(); + + desc.Schema.AddSchema(hdr.SchemaId, _curSchema); + } + _curRawOffset = hdr.GetRawOffset(Stream, pos); _curStruct = new PortableStructureTracker(desc, desc.ReaderTypeStructure); _curRaw = false; @@ -721,6 +734,7 @@ namespace Apache.Ignite.Core.Impl.Portable _curRaw = oldRaw; _curFooterStart = oldFooterStart; _curFooterEnd = oldFooterEnd; + _curSchema = oldSchema; // Process wrappers. We could introduce a common interface, but for only 2 if-else is faster. var wrappedSerializable = obj as SerializableObjectHolder; @@ -744,6 +758,26 @@ namespace Apache.Ignite.Core.Impl.Portable } /// <summary> + /// Reads the schema. + /// </summary> + private int[] ReadSchema() + { + Stream.Seek(_curFooterStart, SeekOrigin.Begin); + + var count = (_curFooterEnd - _curFooterStart) >> 3; + + var res = new int[count]; + + for (int i = 0; i < count; i++) + { + res[i] = Stream.ReadInt(); + Stream.Seek(4, SeekOrigin.Current); + } + + return res; + } + + /// <summary> /// Reads the handle object. /// </summary> private T ReadHandleObject<T>(int pos) @@ -868,11 +902,19 @@ namespace Apache.Ignite.Core.Impl.Portable if (_curRaw) throw new PortableException("Cannot read named fields after raw data is read."); + var actionId = _curStruct.CurStructAction; + var fieldId = _curStruct.GetFieldId(fieldName); - if (!SeekField(fieldId)) - return false; + if (_curSchema == null || actionId >= _curSchema.Length || fieldId != _curSchema[actionId]) + { + _curSchema = null; // read order is different, ignore schema for future reads + + if (!SeekField(fieldId)) + return false; + } + // Expected read order, no need to seek. return IsNotNullHeader(expHdr); } http://git-wip-us.apache.org/repos/asf/ignite/blob/85064003/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSurrogateTypeDescriptor.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSurrogateTypeDescriptor.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSurrogateTypeDescriptor.cs index 8560ce8..71361b4 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSurrogateTypeDescriptor.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/PortableSurrogateTypeDescriptor.cs @@ -43,6 +43,9 @@ namespace Apache.Ignite.Core.Impl.Portable /** Type structure. */ private PortableStructure _readerTypeStructure = PortableStructure.CreateEmpty(); + + /** Type schema. */ + private readonly PortableObjectSchema _schema = new PortableObjectSchema(); /// <summary> /// Constructor. @@ -156,5 +159,11 @@ namespace Apache.Ignite.Core.Impl.Portable _readerTypeStructure = _readerTypeStructure.Merge(exp, pathIdx, updates); } } + + /** <inheritDoc /> */ + public PortableObjectSchema Schema + { + get { return _schema; } + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/85064003/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructureTracker.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructureTracker.cs b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructureTracker.cs index 8cec87a..4b1165d 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructureTracker.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core/Impl/Portable/Structure/PortableStructureTracker.cs @@ -54,6 +54,14 @@ namespace Apache.Ignite.Core.Impl.Portable.Structure } /// <summary> + /// Gets the current structure action. + /// </summary> + public int CurStructAction + { + get { return _curStructAction; } + } + + /// <summary> /// Gets the field ID. /// </summary> public int GetFieldId(string fieldName, byte fieldTypeId = 0)
