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)

Reply via email to