Skip to content

Commit ca57e06

Browse files
authored
Add a few multiplexing microoptimizations (#3918)
Reduced MultiplexingStats allocations. Removed deprecated counter. Moved two Settings.Multiplexing checks to the Debug.Assert.
1 parent b0069e9 commit ca57e06

File tree

3 files changed

+14
-24
lines changed

3 files changed

+14
-24
lines changed

src/Npgsql/Internal/NpgsqlConnector.cs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -184,19 +184,18 @@ public sealed partial class NpgsqlConnector : IDisposable
184184
/// <seealso cref="MultiplexAsyncWritingLock"/>
185185
internal void FlagAsNotWritableForMultiplexing()
186186
{
187-
if (Settings.Multiplexing)
188-
{
189-
Debug.Assert(CommandsInFlightCount > 0 || IsBroken || IsClosed,
187+
Debug.Assert(Settings.Multiplexing);
188+
Debug.Assert(CommandsInFlightCount > 0 || IsBroken || IsClosed,
190189
$"About to mark multiplexing connector as non-writable, but {nameof(CommandsInFlightCount)} is {CommandsInFlightCount}");
191190

192-
Interlocked.Exchange(ref MultiplexAsyncWritingLock, 1);
193-
}
191+
Interlocked.Exchange(ref MultiplexAsyncWritingLock, 1);
194192
}
195193

196194
/// <seealso cref="MultiplexAsyncWritingLock"/>
197195
internal void FlagAsWritableForMultiplexing()
198196
{
199-
if (Settings.Multiplexing && Interlocked.CompareExchange(ref MultiplexAsyncWritingLock, 0, 1) != 1)
197+
Debug.Assert(Settings.Multiplexing);
198+
if (Interlocked.CompareExchange(ref MultiplexAsyncWritingLock, 0, 1) != 1)
200199
throw new Exception("Multiplexing lock was not taken when releasing. Please report a bug.");
201200
}
202201

src/Npgsql/MultiplexingConnectorPool.cs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ public bool IsBootstrapped
2525

2626
volatile bool _isBootstrapped;
2727

28-
readonly ChannelReader<NpgsqlCommand>? _multiplexCommandReader;
29-
internal ChannelWriter<NpgsqlCommand>? MultiplexCommandWriter { get; }
28+
readonly ChannelReader<NpgsqlCommand> _multiplexCommandReader;
29+
internal ChannelWriter<NpgsqlCommand> MultiplexCommandWriter { get; }
3030

3131
/// <summary>
3232
/// A pool-wide type mapper used when multiplexing. This is necessary because binding parameters
@@ -127,9 +127,10 @@ async Task MultiplexingWriteLoop()
127127
// on to the next connector.
128128
Debug.Assert(_multiplexCommandReader != null);
129129

130+
var stats = new MultiplexingStats { Stopwatch = new Stopwatch() };
131+
130132
while (true)
131133
{
132-
var stats = new MultiplexingStats { Stopwatch = new Stopwatch() };
133134
NpgsqlConnector? connector;
134135

135136
// Get a first command out.
@@ -396,7 +397,7 @@ static void CompleteWrite(NpgsqlConnector connector, ref MultiplexingStats stats
396397
// for over-capacity write.
397398
connector.FlagAsWritableForMultiplexing();
398399

399-
NpgsqlEventSource.Log.MultiplexingBatchSent(stats.NumCommands, stats.Waits, stats.Stopwatch!);
400+
NpgsqlEventSource.Log.MultiplexingBatchSent(stats.NumCommands, stats.Stopwatch);
400401
}
401402

402403
// ReSharper disable once FunctionNeverReturns
@@ -406,13 +407,11 @@ struct MultiplexingStats
406407
{
407408
internal Stopwatch Stopwatch;
408409
internal int NumCommands;
409-
internal int Waits;
410410

411411
internal void Reset()
412412
{
413-
Stopwatch.Restart();
414413
NumCommands = 0;
415-
Waits = 0;
414+
Stopwatch.Reset();
416415
}
417416

418417
internal MultiplexingStats Clone()

src/Npgsql/NpgsqlEventSource.cs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,9 @@ sealed class NpgsqlEventSource : EventSource
3131
PollingCounter? _busyConnectionsCounter;
3232

3333
PollingCounter? _multiplexingAverageCommandsPerBatchCounter;
34-
PollingCounter? _multiplexingAverageWaitsPerBatchCounter;
3534
PollingCounter? _multiplexingAverageWriteTimePerBatchCounter;
36-
3735
#endif
36+
3837
long _bytesWritten;
3938
long _bytesRead;
4039

@@ -48,7 +47,6 @@ sealed class NpgsqlEventSource : EventSource
4847

4948
long _multiplexingBatchesSent;
5049
long _multiplexingCommandsSent;
51-
long _multiplexingWaits;
5250
long _multiplexingTicksWritten;
5351

5452
internal NpgsqlEventSource() : base(EventSourceName) {}
@@ -89,12 +87,11 @@ internal void PoolCreated(ConnectorSource pool)
8987
}
9088
}
9189

92-
internal void MultiplexingBatchSent(int numCommands, int waits, Stopwatch stopwatch)
90+
internal void MultiplexingBatchSent(int numCommands, Stopwatch stopwatch)
9391
{
94-
// TODO: CAS loop instead of 4 separate interlocked operations?
92+
// TODO: CAS loop instead of 3 separate interlocked operations?
9593
Interlocked.Increment(ref _multiplexingBatchesSent);
9694
Interlocked.Add(ref _multiplexingCommandsSent, numCommands);
97-
Interlocked.Add(ref _multiplexingWaits, waits);
9895
Interlocked.Add(ref _multiplexingTicksWritten, stopwatch.ElapsedTicks);
9996
}
10097

@@ -209,11 +206,6 @@ protected override void OnEventCommand(EventCommandEventArgs command)
209206
DisplayName = "Average commands per multiplexing batch"
210207
};
211208

212-
_multiplexingAverageWaitsPerBatchCounter = new PollingCounter("multiplexing-average-waits-per-batch", this, () => (double)Interlocked.Read(ref _multiplexingWaits) / Interlocked.Read(ref _multiplexingBatchesSent))
213-
{
214-
DisplayName = "Average waits per multiplexing batch"
215-
};
216-
217209
_multiplexingAverageWriteTimePerBatchCounter = new PollingCounter("multiplexing-average-write-time-per-batch", this, () => (double)Interlocked.Read(ref _multiplexingTicksWritten) / Interlocked.Read(ref _multiplexingBatchesSent) / 1000)
218210
{
219211
DisplayName = "Average write time per multiplexing batch (us)",

0 commit comments

Comments
 (0)