Skip to content

Commit f47a3ca

Browse files
committed
Merge pull request #15 from huan086/master
Reduce number of calls to JsPool._metadata indexer to reduce synchron…
2 parents 12d5cd6 + 4f3fcb8 commit f47a3ca

File tree

2 files changed

+21
-26
lines changed

2 files changed

+21
-26
lines changed

src/JSPool.Tests/JsPoolTests.cs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public class JsPoolTests
2121
public void ConstructorCreatesEngines()
2222
{
2323
var factory = new Mock<IEngineFactoryForMock>();
24-
factory.Setup(x => x.EngineFactory()).Returns(new Mock<IJsEngine>().Object);
24+
factory.Setup(x => x.EngineFactory()).Returns(() => new Mock<IJsEngine>().Object);
2525
var config = new JsPoolConfig
2626
{
2727
StartEngines = 5,
@@ -72,7 +72,7 @@ public void GetEngineReturnsAllAvailableEngines()
7272
public void GetEngineCreatesNewEngineIfNotAtMaximum()
7373
{
7474
var factory = new Mock<IEngineFactoryForMock>();
75-
factory.Setup(x => x.EngineFactory()).Returns(new Mock<IJsEngine>().Object);
75+
factory.Setup(x => x.EngineFactory()).Returns(() => new Mock<IJsEngine>().Object);
7676
var config = new JsPoolConfig
7777
{
7878
StartEngines = 1,
@@ -97,7 +97,7 @@ public void GetEngineCreatesNewEngineIfNotAtMaximum()
9797
public void GetEngineFailsIfAtMaximum()
9898
{
9999
var factory = new Mock<IEngineFactoryForMock>();
100-
factory.Setup(x => x.EngineFactory()).Returns(new Mock<IJsEngine>().Object);
100+
factory.Setup(x => x.EngineFactory()).Returns(() => new Mock<IJsEngine>().Object);
101101
var config = new JsPoolConfig
102102
{
103103
StartEngines = 1,
@@ -109,7 +109,7 @@ public void GetEngineFailsIfAtMaximum()
109109
factory.Verify(x => x.EngineFactory(), Times.Exactly(2));
110110
pool.GetEngine(); // First engine created on init
111111

112-
Assert.Throws<JsPoolExhaustedException>(() =>
112+
Assert.Throws<JsPoolExhaustedException>(() =>
113113
pool.GetEngine(TimeSpan.Zero)
114114
);
115115
}
@@ -118,7 +118,7 @@ public void GetEngineFailsIfAtMaximum()
118118
public void ReturnEngineToPoolAddsToAvailableEngines()
119119
{
120120
var factory = new Mock<IEngineFactoryForMock>();
121-
factory.Setup(x => x.EngineFactory()).Returns(new Mock<IJsEngine>().Object);
121+
factory.Setup(x => x.EngineFactory()).Returns(() => new Mock<IJsEngine>().Object);
122122
var config = new JsPoolConfig
123123
{
124124
StartEngines = 2,
@@ -138,7 +138,7 @@ public void ReturnEngineDisposesIfAtMaxUsages()
138138
{
139139
var mockEngine1 = new Mock<IJsEngine>();
140140
var mockEngine2 = new Mock<IJsEngine>();
141-
var factory = new Mock<IEngineFactoryForMock>();
141+
var factory = new Mock<IEngineFactoryForMock>();
142142
factory.SetupSequence(x => x.EngineFactory())
143143
// First engine is a dummy engine to check functionality
144144
.Returns(new Mock<IJsEngine>().Object)
@@ -229,7 +229,7 @@ public void ShouldIgnoreReturnToPoolIfUnknownEngine()
229229
public void RecycleCreatesNewEngines()
230230
{
231231
var factory = new Mock<IEngineFactoryForMock>();
232-
factory.Setup(x => x.EngineFactory()).Returns(new Mock<IJsEngine>().Object);
232+
factory.Setup(x => x.EngineFactory()).Returns(() => new Mock<IJsEngine>().Object);
233233
var config = new JsPoolConfig
234234
{
235235
StartEngines = 2,
@@ -254,7 +254,7 @@ public void RecycleFiresRecycledEvent()
254254
{
255255
var callCount = 0;
256256
var factory = new Mock<IEngineFactoryForMock>();
257-
factory.Setup(x => x.EngineFactory()).Returns(new Mock<IJsEngine>().Object);
257+
factory.Setup(x => x.EngineFactory()).Returns(() => new Mock<IJsEngine>().Object);
258258
var config = new JsPoolConfig
259259
{
260260
StartEngines = 2,
@@ -276,7 +276,7 @@ public void RecycleFiresRecycledEvent()
276276
public void WatchPathWithoutWatchFilesDoesNotThrow()
277277
{
278278
var factory = new Mock<IEngineFactoryForMock>();
279-
factory.Setup(x => x.EngineFactory()).Returns(new Mock<IJsEngine>().Object);
279+
factory.Setup(x => x.EngineFactory()).Returns(() => new Mock<IJsEngine>().Object);
280280
var config = new JsPoolConfig
281281
{
282282
StartEngines = 2,
@@ -287,7 +287,7 @@ public void WatchPathWithoutWatchFilesDoesNotThrow()
287287
{
288288
// ReSharper disable once UnusedVariable
289289
var pool = new JsPool(config);
290-
});
290+
});
291291
}
292292
}
293293

src/JSPool/JsPool.cs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,10 @@ public class JsPool : IJsPool
3030
/// </summary>
3131
protected readonly BlockingCollection<IJsEngine> _availableEngines = new BlockingCollection<IJsEngine>();
3232
/// <summary>
33-
/// Metadata for the engines.
33+
/// Metadata for the engines. Total number of engines that have been created is reflected in its Count.
3434
/// </summary>
3535
protected readonly IDictionary<IJsEngine, EngineMetadata> _metadata = new ConcurrentDictionary<IJsEngine, EngineMetadata>();
3636
/// <summary>
37-
/// Totan number of engines that have been created.
38-
/// </summary>
39-
protected int _engineCount;
40-
/// <summary>
4137
/// Factory method used to create engines.
4238
/// </summary>
4339
protected readonly Func<IJsEngine> _engineFactory;
@@ -131,7 +127,6 @@ protected virtual IJsEngine CreateEngine()
131127
var engine = _engineFactory();
132128
_config.Initializer(engine);
133129
_metadata[engine] = new EngineMetadata();
134-
Interlocked.Increment(ref _engineCount);
135130
return engine;
136131
}
137132

@@ -190,8 +185,9 @@ public virtual IJsEngine GetEngine(TimeSpan? timeout = null)
190185
/// <param name="engine"></param>
191186
private IJsEngine TakeEngine(IJsEngine engine)
192187
{
193-
_metadata[engine].InUse = true;
194-
_metadata[engine].UsageCount++;
188+
var metadata = _metadata[engine];
189+
metadata.InUse = true;
190+
metadata.UsageCount++;
195191
return engine;
196192
}
197193

@@ -201,7 +197,8 @@ private IJsEngine TakeEngine(IJsEngine engine)
201197
/// <param name="engine">Engine to return</param>
202198
public virtual void ReturnEngineToPool(IJsEngine engine)
203199
{
204-
if (!_metadata.ContainsKey(engine))
200+
EngineMetadata metadata;
201+
if (!_metadata.TryGetValue(engine, out metadata))
205202
{
206203
// This engine was from another pool. This could happen if a pool is recycled
207204
// and replaced with a different one (like what ReactJS.NET does when any
@@ -210,17 +207,17 @@ public virtual void ReturnEngineToPool(IJsEngine engine)
210207
return;
211208
}
212209

213-
_metadata[engine].InUse = false;
214-
var usageCount = _metadata[engine].UsageCount;
215-
if (_config.MaxUsagesPerEngine > 0 && usageCount >= _config.MaxUsagesPerEngine)
210+
metadata.InUse = false;
211+
var usageCount = metadata.UsageCount;
212+
if (_config.MaxUsagesPerEngine > 0 && usageCount >= _config.MaxUsagesPerEngine)
216213
{
217214
// Engine has been reused the maximum number of times, recycle it.
218215
DisposeEngine(engine);
219216
return;
220217
}
221218

222219
if (
223-
_config.GarbageCollectionInterval > 0 &&
220+
_config.GarbageCollectionInterval > 0 &&
224221
usageCount % _config.GarbageCollectionInterval == 0 &&
225222
engine.SupportsGarbageCollection()
226223
)
@@ -242,7 +239,6 @@ public virtual void DisposeEngine(IJsEngine engine, bool repopulateEngines = tru
242239
{
243240
engine.Dispose();
244241
_metadata.Remove(engine);
245-
Interlocked.Decrement(ref _engineCount);
246242

247243
if (repopulateEngines)
248244
{
@@ -266,7 +262,6 @@ protected virtual void DisposeAllEngines()
266262
// Also clear out all metadata so engines that are currently in use while this disposal is
267263
// happening get disposed on return.
268264
_metadata.Clear();
269-
_engineCount = 0;
270265
}
271266

272267
/// <summary>
@@ -303,7 +298,7 @@ public virtual void Dispose()
303298
/// </summary>
304299
public virtual int EngineCount
305300
{
306-
get { return _engineCount; }
301+
get { return _metadata.Count; }
307302
}
308303

309304
/// <summary>

0 commit comments

Comments
 (0)