Skip to content

Commit b904270

Browse files
authored
Merge pull request #145 from servicetitan/OptimizeSessionConstructor
Optimized Session constructor
2 parents 3263519 + 49feb48 commit b904270

File tree

19 files changed

+537
-568
lines changed

19 files changed

+537
-568
lines changed

Orm/Xtensive.Orm/Caching/WeakCache.cs

Lines changed: 64 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
// Copyright (C) 2003-2010 Xtensive LLC.
2-
// All rights reserved.
3-
// For conditions of distribution and use, see license.
1+
// Copyright (C) 2003-2021 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
44
// Created by: Alex Ustinov
55
// Created: 2007.05.28
66

77
using System;
88
using System.Collections;
99
using System.Collections.Generic;
1010
using System.Diagnostics;
11+
using System.Linq;
1112
using System.Runtime.InteropServices;
1213
using System.Security;
1314
using Xtensive.Core;
@@ -34,7 +35,6 @@ public class WeakCache<TKey, TItem> :
3435
/// </summary>
3536
protected const int NoGcCount = 1024;
3637

37-
private const int GcOperationCost = 2;
3838
private readonly bool trackResurrection;
3939
private readonly Converter<TItem, TKey> keyExtractor;
4040
private Dictionary<TKey, GCHandle> items;
@@ -43,48 +43,44 @@ public class WeakCache<TKey, TItem> :
4343
#region Properites: KeyExtractor, ChainedCache, TrackResurrection, EfficiencyFactor, Count, Size
4444

4545
/// <inheritdoc/>
46-
public Converter<TItem, TKey> KeyExtractor {
46+
public Converter<TItem, TKey> KeyExtractor
47+
{
4748
[DebuggerStepThrough]
48-
get { return keyExtractor; }
49+
get => keyExtractor;
4950
}
5051

5152
/// <summary>
5253
/// Gets a value indicating whether this cache tracks resurrection.
5354
/// </summary>
54-
public bool TrackResurrection {
55+
public bool TrackResurrection
56+
{
5557
[DebuggerStepThrough]
56-
get { return trackResurrection; }
58+
get => trackResurrection;
5759
}
5860

5961
/// <inheritdoc/>
60-
public int Count {
62+
public int Count
63+
{
6164
[DebuggerStepThrough]
62-
get { return items.Count; }
65+
get => items?.Count ?? 0;
6366
}
6467

6568
#endregion
6669

6770
/// <inheritdoc/>
68-
public TItem this[TKey key, bool markAsHit] {
69-
get {
70-
TItem item;
71-
if (TryGetItem(key, markAsHit, out item))
72-
return item;
73-
else
74-
return null;
75-
}
76-
}
71+
public TItem this[TKey key, bool markAsHit] => TryGetItem(key, markAsHit, out var item) ? item : null;
7772

7873
/// <inheritdoc/>
7974
[SecuritySafeCritical]
8075
public virtual bool TryGetItem(TKey key, bool markAsHit, out TItem item)
8176
{
8277
RegisterOperation(1);
83-
GCHandle cached;
84-
if (items.TryGetValue(key, out cached)) {
85-
item = (TItem) cached.Target;
86-
if (item!=null)
78+
if (items != null && items.TryGetValue(key, out var cached)) {
79+
item = ExtractTarget(cached);
80+
if (item != null) {
8781
return true;
82+
}
83+
8884
items.Remove(key);
8985
cached.Free();
9086
return false;
@@ -94,113 +90,103 @@ public virtual bool TryGetItem(TKey key, bool markAsHit, out TItem item)
9490
}
9591

9692
/// <inheritdoc/>
97-
public bool Contains(TItem item)
98-
{
99-
return ContainsKey(KeyExtractor(item));
100-
}
93+
public bool Contains(TItem item) => ContainsKey(KeyExtractor(item));
10194

10295
/// <inheritdoc/>
103-
public bool ContainsKey(TKey key)
104-
{
105-
TItem item;
106-
return TryGetItem(key, false, out item);
107-
}
96+
public bool ContainsKey(TKey key) => TryGetItem(key, false, out var _);
10897

10998
#region Modification methods: Add, Remove, Clear
11099

111100
/// <inheritdoc/>
112-
public void Add(TItem item)
113-
{
114-
Add(item, true);
115-
}
101+
public void Add(TItem item) => Add(item, true);
116102

117103
/// <inheritdoc/>
118104
[SecuritySafeCritical]
119105
public virtual TItem Add(TItem item, bool replaceIfExists)
120106
{
121-
ArgumentValidator.EnsureArgumentNotNull(item, "item");
107+
ArgumentValidator.EnsureArgumentNotNull(item, nameof(item));
122108
RegisterOperation(2);
123109
var key = KeyExtractor(item);
124-
GCHandle cached;
125-
if (items.TryGetValue(key, out cached)) {
126-
if (!replaceIfExists) {
127-
var cachedItem = (TItem) cached.Target;
128-
if (cachedItem!=null)
129-
return cachedItem;
110+
if (items == null) {
111+
items = CreateDictionary();
112+
}
113+
else if (replaceIfExists) {
114+
if (items.Remove(key, out var cached)) {
115+
cached.Free();
116+
}
117+
}
118+
else if (items.TryGetValue(key, out var cached)) {
119+
if (ExtractTarget(cached) is TItem cachedItem) {
120+
return cachedItem;
130121
}
131122
items.Remove(key);
132123
cached.Free();
133124
}
134-
items[key] = GCHandle.Alloc(item,
135-
trackResurrection ? GCHandleType.WeakTrackResurrection : GCHandleType.Weak);
125+
items[key] = GCHandle.Alloc(item, trackResurrection ? GCHandleType.WeakTrackResurrection : GCHandleType.Weak);
136126
return item;
137127
}
138128

139129
/// <inheritdoc/>
140130
public void Remove(TItem item)
141131
{
142-
ArgumentValidator.EnsureArgumentNotNull(item, "item");
132+
ArgumentValidator.EnsureArgumentNotNull(item, nameof(item));
143133
RemoveKey(KeyExtractor(item));
144134
}
145135

146136
/// <inheritdoc/>
147137
[SecuritySafeCritical]
148138
public virtual void RemoveKey(TKey key)
149139
{
150-
GCHandle cached;
151-
if (items.TryGetValue(key, out cached)) {
152-
items.Remove(key);
140+
if (items != null && items.Remove(key, out var cached) == true) {
153141
cached.Free();
154142
}
155143
}
156144

157145
/// <inheritdoc/>
158-
public void RemoveKey(TKey key, bool removeCompletely)
159-
{
160-
RemoveKey(key);
161-
}
146+
public void RemoveKey(TKey key, bool removeCompletely) => RemoveKey(key);
162147

163148
/// <inheritdoc/>
164149
[SecuritySafeCritical]
165150
public virtual void Clear()
166151
{
152+
if (items == null) {
153+
return;
154+
}
167155
try {
168-
foreach (var pair in items)
156+
foreach (var pair in items) {
169157
try {
170158
pair.Value.Free();
171159
}
172-
catch {}
160+
catch { }
161+
}
173162
}
174163
finally {
175-
items = new Dictionary<TKey, GCHandle>();
164+
items = null;
176165
time = 0;
177166
}
178167
}
179168

180169
/// <inheritdoc/>
181-
public void Invalidate()
182-
{
183-
Clear();
184-
}
170+
public void Invalidate() => Clear();
185171

186172
/// <inheritdoc/>
187173
[SecuritySafeCritical]
188174
public virtual void CollectGarbage()
189175
{
190-
int count = items.Count;
191-
if (count<=NoGcCount)
176+
var count = items?.Count ?? 0;
177+
if (count <= NoGcCount) {
192178
return;
179+
}
193180

194181
Exception error = null;
195182
int removedCount = 0;
196183
try {
197184
// Filtering
198-
var newItems = new Dictionary<TKey, GCHandle>();
199-
foreach (var pair in items) {
200-
var cached = pair.Value;
185+
var newItems = CreateDictionary();
186+
foreach (var (key, cached) in items) {
201187
var item = cached.Target;
202-
if (item!=null)
203-
newItems.Add(pair.Key, cached);
188+
if (item != null)
189+
newItems.Add(key, cached);
204190
else
205191
cached.Free();
206192
}
@@ -217,7 +203,7 @@ public virtual void CollectGarbage()
217203
// Logging
218204
if (CoreLog.IsLogged(LogLevel.Debug)) {
219205
CoreLog.Debug("WeakCache.CollectGarbage: removed: {0} from {1}", removedCount, count);
220-
if (error!=null)
206+
if (error != null)
221207
CoreLog.Debug(error, "Caught at WeakCache.CollectGarbage");
222208
}
223209
}
@@ -229,39 +215,33 @@ public virtual void CollectGarbage()
229215

230216
/// <inheritdoc/>
231217
[DebuggerStepThrough]
232-
IEnumerator IEnumerable.GetEnumerator()
233-
{
234-
return GetEnumerator();
235-
}
218+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
236219

237220
/// <inheritdoc/>
238221
public virtual IEnumerator<TItem> GetEnumerator()
239222
{
240-
foreach (var pair in items) {
241-
var item = ExtractTarget(pair.Value);
242-
if (item!=null)
223+
foreach (var pair in items ?? Enumerable.Empty<KeyValuePair<TKey, GCHandle>>()) {
224+
if (ExtractTarget(pair.Value) is TItem item)
243225
yield return item;
244226
}
245227
}
246228

247229
[SecuritySafeCritical]
248-
private static TItem ExtractTarget(GCHandle handle)
249-
{
250-
return (TItem) handle.Target;
251-
}
230+
private static TItem ExtractTarget(GCHandle handle) => (TItem) handle.Target;
252231

253232
#endregion
254233

255234
#region Private / internal methods
256235

236+
private static Dictionary<TKey, GCHandle> CreateDictionary() => new Dictionary<TKey, GCHandle>();
237+
257238
private void RegisterOperation(int weight)
258239
{
259240
time += weight;
260-
var count = items.Count;
261-
if (count <= NoGcCount)
262-
return;
263-
if (time > ((count << 1) + count))
241+
var count = items?.Count ?? 0;
242+
if (count > NoGcCount && time > (count << 1) + count) {
264243
CollectGarbage();
244+
}
265245
}
266246

267247
#endregion
@@ -279,7 +259,6 @@ public WeakCache(bool trackResurrection, Converter<TItem, TKey> keyExtractor)
279259
ArgumentValidator.EnsureArgumentNotNull(keyExtractor, "keyExtractor");
280260
this.trackResurrection = trackResurrection;
281261
this.keyExtractor = keyExtractor;
282-
items = new Dictionary<TKey, GCHandle>(1024);
283262
}
284263

285264
// Dispose pattern
@@ -290,14 +269,7 @@ public WeakCache(bool trackResurrection, Converter<TItem, TKey> keyExtractor)
290269
[SecuritySafeCritical]
291270
protected virtual void Dispose(bool disposing)
292271
{
293-
if (items!=null) {
294-
try {
295-
Clear();
296-
}
297-
finally {
298-
items = null;
299-
}
300-
}
272+
Clear();
301273
}
302274

303275
/// <summary>

0 commit comments

Comments
 (0)