Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit d6be92a

Browse files
authored
Merge pull request #565 from ServiceStack/netcore
Add cache for index fields
2 parents 63761f1 + 9a15848 commit d6be92a

File tree

5 files changed

+96
-5
lines changed

5 files changed

+96
-5
lines changed

.vscode/launch.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"type": "coreclr",
77
"request": "launch",
88
"preLaunchTask": "build",
9-
"program": "${workspaceRoot}/tests/ServiceStack.OrmLite.Tests/bin/Debug/netcoreapp1.0/ServiceStack.OrmLite.Tests.dll",
9+
"program": "${workspaceRoot}/tests/ServiceStack.OrmLite.Tests/bin/Debug/netcoreapp1.1/ServiceStack.OrmLite.Tests.dll",
1010
"args": ["--test=ServiceStack.OrmLite.Tests._TypeDescriptorMetadataTests.Can_add_AutoIncrement_Id_at_runtime"],
1111
"cwd": "${workspaceRoot}",
1212
"stopAtEntry": false,
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Data;
5+
6+
namespace ServiceStack.OrmLite
7+
{
8+
public class IndexFieldsCacheKey
9+
{
10+
int hashCode;
11+
12+
public ModelDefinition ModelDefinition { get; private set; }
13+
14+
public IOrmLiteDialectProvider Dialect { get; private set; }
15+
16+
public List<string> Fields { get; private set; }
17+
18+
public IndexFieldsCacheKey(IDataReader reader, ModelDefinition modelDefinition, IOrmLiteDialectProvider dialect)
19+
{
20+
ModelDefinition = modelDefinition;
21+
Dialect = dialect;
22+
23+
int startPos = 0;
24+
int endPos = reader.FieldCount;
25+
26+
Fields = new List<string>(endPos - startPos);
27+
28+
for (int i = startPos; i < endPos; i++)
29+
Fields.Add(reader.GetName(i));
30+
31+
unchecked
32+
{
33+
hashCode = 17;
34+
hashCode = hashCode * 23 + ModelDefinition.GetHashCode();
35+
hashCode = hashCode * 23 + Dialect.GetHashCode();
36+
hashCode = hashCode * 23 + Fields.Count;
37+
for (int i = 0; i < Fields.Count; i++)
38+
hashCode = hashCode * 23 + Fields[i].Length;
39+
}
40+
}
41+
42+
public override bool Equals (object obj)
43+
{
44+
var that = obj as IndexFieldsCacheKey;
45+
46+
if (obj == null) return false;
47+
48+
return this.ModelDefinition == that.ModelDefinition
49+
&& this.Dialect == that.Dialect
50+
&& this.Fields.Count == that.Fields.Count
51+
&& this.Fields.SequenceEqual(that.Fields);
52+
}
53+
54+
public override int GetHashCode()
55+
{
56+
return hashCode;
57+
}
58+
}
59+
}

src/ServiceStack.OrmLite/OrmLiteUtils.cs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ public static class OrmLiteUtils
3131
{
3232
internal const string AsyncRequiresNet45Error = "Async support is only available in .NET 4.5 builds";
3333

34+
const int maxCachedIndexFields = 10000;
35+
private static Dictionary<IndexFieldsCacheKey, Tuple<FieldDefinition, int, IOrmLiteConverter>[]> indexFieldsCache
36+
= new Dictionary<IndexFieldsCacheKey, Tuple<FieldDefinition, int, IOrmLiteConverter>[]>(maxCachedIndexFields);
37+
3438
public static void DebugCommand(this ILog log, IDbCommand cmd)
3539
{
3640
var sb = StringBuilderCache.Allocate();
@@ -160,7 +164,7 @@ public static List<T> ConvertToList<T>(this IDataReader reader, IOrmLiteDialectP
160164
}
161165
return (List<T>)(object)to.ToList();
162166
}
163-
if (typeof(T).Name.StartsWith("Tuple`"))
167+
if (typeof(T).Name.StartsWith("Tuple`", StringComparison.Ordinal))
164168
{
165169
var to = new List<T>();
166170
using (reader)
@@ -491,12 +495,25 @@ public static Tuple<FieldDefinition, int, IOrmLiteConverter>[] GetIndexFieldsCac
491495
int startPos=0,
492496
int? endPos = null)
493497
{
498+
var end = endPos.GetValueOrDefault(reader.FieldCount);
499+
var cacheKey = (startPos == 0 && end == reader.FieldCount && onlyFields == null)
500+
? new IndexFieldsCacheKey(reader, modelDefinition, dialect)
501+
: null;
502+
503+
if (cacheKey != null)
504+
{
505+
lock (indexFieldsCache)
506+
{
507+
if (indexFieldsCache.ContainsKey(cacheKey))
508+
return indexFieldsCache[cacheKey];
509+
}
510+
}
511+
494512
var cache = new List<Tuple<FieldDefinition, int, IOrmLiteConverter>>();
495513
var ignoredFields = modelDefinition.IgnoredFieldDefinitions;
496514
var remainingFieldDefs = modelDefinition.FieldDefinitionsArray
497515
.Where(x => !ignoredFields.Contains(x) && x.SetValueFn != null).ToList();
498516

499-
var end = endPos.GetValueOrDefault(reader.FieldCount);
500517
var mappedReaderColumns = new bool[end];
501518

502519
for (var i = startPos; i < end; i++)
@@ -549,7 +566,20 @@ public static Tuple<FieldDefinition, int, IOrmLiteConverter>[] GetIndexFieldsCac
549566
}
550567
}
551568

552-
return cache.ToArray();
569+
var result = cache.ToArray();
570+
571+
if (cacheKey != null)
572+
{
573+
lock(indexFieldsCache)
574+
{
575+
if (indexFieldsCache.ContainsKey(cacheKey))
576+
return indexFieldsCache[cacheKey];
577+
else if (indexFieldsCache.Count < maxCachedIndexFields)
578+
indexFieldsCache.Add(cacheKey, result);
579+
}
580+
}
581+
582+
return result;
553583
}
554584

555585
private const int NotFound = -1;

src/ServiceStack.OrmLite/ServiceStack.OrmLite.Signed.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@
249249
<Compile Include="Support\LoadList.cs" />
250250
<Compile Include="Support\LoadReferences.cs" />
251251
<Compile Include="UntypedApi.cs" />
252+
<Compile Include="IndexFieldsCacheKey.cs" />
252253
</ItemGroup>
253254
<ItemGroup>
254255
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">

src/ServiceStack.OrmLite/ServiceStack.OrmLite.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,8 @@
243243
<Compile Include="Support\LoadList.cs" />
244244
<Compile Include="Support\LoadReferences.cs" />
245245
<Compile Include="UntypedApi.cs" />
246-
</ItemGroup>
246+
<Compile Include="IndexFieldsCacheKey.cs" />
247+
</ItemGroup>
247248
<ItemGroup>
248249
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
249250
<Visible>False</Visible>

0 commit comments

Comments
 (0)