Skip to content

Commit a59b39d

Browse files
committed
Add single-entry MRU connection pool cache.
Most applications use just one connection string; add a fast path that uses a single-entry MRU cache to store the most recent connection string and its pool.
1 parent d830aa9 commit a59b39d

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

src/MySqlConnector/Core/ConnectionPool.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,15 +340,25 @@ private async Task CreateMinimumPooledSessions(IOBehavior ioBehavior, Cancellati
340340

341341
public static ConnectionPool GetPool(string connectionString)
342342
{
343+
// check single-entry MRU cache for this exact connection string; most applications have just one
344+
// connection string and will get a cache hit here
345+
var cache = s_mruCache;
346+
if (cache?.ConnectionString == connectionString)
347+
return cache.Pool;
348+
343349
// check if pool has already been created for this exact connection string
344350
if (s_pools.TryGetValue(connectionString, out var pool))
351+
{
352+
s_mruCache = new ConnectionStringPool(connectionString, pool);
345353
return pool;
354+
}
346355

347356
// parse connection string and check for 'Pooling' setting; return 'null' if pooling is disabled
348357
var connectionStringBuilder = new MySqlConnectionStringBuilder(connectionString);
349358
if (!connectionStringBuilder.Pooling)
350359
{
351360
s_pools.GetOrAdd(connectionString, default(ConnectionPool));
361+
s_mruCache = new ConnectionStringPool(connectionString, null);
352362
return null;
353363
}
354364

@@ -359,6 +369,7 @@ public static ConnectionPool GetPool(string connectionString)
359369
// try to set the pool for the connection string to the canonical pool; if someone else
360370
// beats us to it, just use the existing value
361371
pool = s_pools.GetOrAdd(connectionString, pool);
372+
s_mruCache = new ConnectionStringPool(connectionString, pool);
362373
return pool;
363374
}
364375

@@ -369,9 +380,14 @@ public static ConnectionPool GetPool(string connectionString)
369380

370381
// if we won the race to create the new pool, also store it under the original connection string
371382
if (pool == newPool && connectionString != normalizedConnectionString)
383+
{
372384
s_pools.GetOrAdd(connectionString, pool);
385+
s_mruCache = new ConnectionStringPool(connectionString, pool);
386+
}
373387
else if (pool != newPool && Log.IsInfoEnabled())
388+
{
374389
Log.Info("{0} was created but will not be used (due to race)", newPool.m_logArguments[0]);
390+
}
375391

376392
return pool;
377393
}
@@ -448,6 +464,18 @@ public IEnumerable<string> LoadBalance(IReadOnlyList<string> hosts)
448464
readonly ConnectionPool m_pool;
449465
}
450466

467+
private sealed class ConnectionStringPool
468+
{
469+
public ConnectionStringPool(string connectionString, ConnectionPool pool)
470+
{
471+
ConnectionString = connectionString;
472+
Pool = pool;
473+
}
474+
475+
public string ConnectionString { get; }
476+
public ConnectionPool Pool { get; }
477+
}
478+
451479
static readonly IMySqlConnectorLogger Log = MySqlConnectorLogManager.CreateLogger(nameof(ConnectionPool));
452480
static readonly ConcurrentDictionary<string, ConnectionPool> s_pools = new ConcurrentDictionary<string, ConnectionPool>();
453481
#if DEBUG
@@ -472,6 +500,7 @@ public IEnumerable<string> LoadBalance(IReadOnlyList<string> hosts)
472500
});
473501

474502
static int s_poolId;
503+
static ConnectionStringPool s_mruCache;
475504

476505
int m_generation;
477506
readonly SemaphoreSlim m_cleanSemaphore;

0 commit comments

Comments
 (0)