Skip to content

Commit ec6be85

Browse files
authored
Reduce allocation in query for execution strategy (#24208)
1 parent 15115d8 commit ec6be85

File tree

4 files changed

+120
-96
lines changed

4 files changed

+120
-96
lines changed

src/EFCore.Relational/Query/Internal/FromSqlQueryingEnumerable.cs

+32-26
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ public bool MoveNext()
196196
if (_dataReader == null)
197197
{
198198
_relationalQueryContext.ExecutionStrategyFactory.Create()
199-
.Execute(true, InitializeReader, null);
199+
.Execute(this, (_, enumerator) => InitializeReader(enumerator), null);
200200
}
201201

202202
var hasNext = _dataReader!.Read();
@@ -220,26 +220,27 @@ public bool MoveNext()
220220
}
221221
}
222222

223-
private bool InitializeReader(DbContext _, bool result)
223+
private static bool InitializeReader(Enumerator enumerator)
224224
{
225225
EntityFrameworkEventSource.Log.QueryExecuting();
226226

227-
var relationalCommand = _relationalCommandCache.GetRelationalCommand(_relationalQueryContext.ParameterValues);
227+
var relationalCommand = enumerator._relationalCommandCache.GetRelationalCommand(
228+
enumerator._relationalQueryContext.ParameterValues);
228229

229-
_dataReader = relationalCommand.ExecuteReader(
230+
enumerator._dataReader = relationalCommand.ExecuteReader(
230231
new RelationalCommandParameterObject(
231-
_relationalQueryContext.Connection,
232-
_relationalQueryContext.ParameterValues,
233-
_relationalCommandCache.ReaderColumns,
234-
_relationalQueryContext.Context,
235-
_relationalQueryContext.CommandLogger,
236-
_detailedErrorsEnabled));
232+
enumerator._relationalQueryContext.Connection,
233+
enumerator._relationalQueryContext.ParameterValues,
234+
enumerator._relationalCommandCache.ReaderColumns,
235+
enumerator._relationalQueryContext.Context,
236+
enumerator._relationalQueryContext.CommandLogger,
237+
enumerator._detailedErrorsEnabled));
237238

238-
_indexMap = BuildIndexMap(_columnNames, _dataReader.DbDataReader);
239+
enumerator._indexMap = BuildIndexMap(enumerator._columnNames, enumerator._dataReader.DbDataReader);
239240

240-
_relationalQueryContext.InitializeStateManager(_standAloneStateManager);
241+
enumerator._relationalQueryContext.InitializeStateManager(enumerator._standAloneStateManager);
241242

242-
return result;
243+
return false;
243244
}
244245

245246
public void Dispose()
@@ -297,7 +298,11 @@ public async ValueTask<bool> MoveNextAsync()
297298
if (_dataReader == null)
298299
{
299300
await _relationalQueryContext.ExecutionStrategyFactory.Create()
300-
.ExecuteAsync(true, InitializeReaderAsync, null, _relationalQueryContext.CancellationToken)
301+
.ExecuteAsync(
302+
this,
303+
(_, enumerator, cancellationToken) => InitializeReaderAsync(enumerator, cancellationToken),
304+
null,
305+
_relationalQueryContext.CancellationToken)
301306
.ConfigureAwait(false);
302307
}
303308

@@ -322,28 +327,29 @@ await _relationalQueryContext.ExecutionStrategyFactory.Create()
322327
}
323328
}
324329

325-
private async Task<bool> InitializeReaderAsync(DbContext _, bool result, CancellationToken cancellationToken)
330+
private static async Task<bool> InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
326331
{
327332
EntityFrameworkEventSource.Log.QueryExecuting();
328333

329-
var relationalCommand = _relationalCommandCache.GetRelationalCommand(_relationalQueryContext.ParameterValues);
334+
var relationalCommand = enumerator._relationalCommandCache.GetRelationalCommand(
335+
enumerator._relationalQueryContext.ParameterValues);
330336

331-
_dataReader = await relationalCommand.ExecuteReaderAsync(
337+
enumerator._dataReader = await relationalCommand.ExecuteReaderAsync(
332338
new RelationalCommandParameterObject(
333-
_relationalQueryContext.Connection,
334-
_relationalQueryContext.ParameterValues,
335-
_relationalCommandCache.ReaderColumns,
336-
_relationalQueryContext.Context,
337-
_relationalQueryContext.CommandLogger,
338-
_detailedErrorsEnabled),
339+
enumerator._relationalQueryContext.Connection,
340+
enumerator._relationalQueryContext.ParameterValues,
341+
enumerator._relationalCommandCache.ReaderColumns,
342+
enumerator._relationalQueryContext.Context,
343+
enumerator._relationalQueryContext.CommandLogger,
344+
enumerator._detailedErrorsEnabled),
339345
cancellationToken)
340346
.ConfigureAwait(false);
341347

342-
_indexMap = BuildIndexMap(_columnNames, _dataReader.DbDataReader);
348+
enumerator._indexMap = BuildIndexMap(enumerator._columnNames, enumerator._dataReader.DbDataReader);
343349

344-
_relationalQueryContext.InitializeStateManager(_standAloneStateManager);
350+
enumerator._relationalQueryContext.InitializeStateManager(enumerator._standAloneStateManager);
345351

346-
return result;
352+
return false;
347353
}
348354

349355
public ValueTask DisposeAsync()

src/EFCore.Relational/Query/Internal/SingleQueryingEnumerable.cs

+32-26
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ public bool MoveNext()
163163
if (_dataReader == null)
164164
{
165165
_relationalQueryContext.ExecutionStrategyFactory.Create()
166-
.Execute(true, InitializeReader, null);
166+
.Execute(this, (_, enumerator) => InitializeReader(enumerator), null);
167167
}
168168

169169
var hasNext = _resultCoordinator!.HasNext ?? _dataReader!.Read();
@@ -214,26 +214,27 @@ public bool MoveNext()
214214
}
215215
}
216216

217-
private bool InitializeReader(DbContext _, bool result)
217+
private static bool InitializeReader(Enumerator enumerator)
218218
{
219219
EntityFrameworkEventSource.Log.QueryExecuting();
220220

221-
var relationalCommand = _relationalCommandCache.GetRelationalCommand(_relationalQueryContext.ParameterValues);
221+
var relationalCommand = enumerator._relationalCommandCache.GetRelationalCommand(
222+
enumerator._relationalQueryContext.ParameterValues);
222223

223-
_dataReader = relationalCommand.ExecuteReader(
224+
enumerator._dataReader = relationalCommand.ExecuteReader(
224225
new RelationalCommandParameterObject(
225-
_relationalQueryContext.Connection,
226-
_relationalQueryContext.ParameterValues,
227-
_relationalCommandCache.ReaderColumns,
228-
_relationalQueryContext.Context,
229-
_relationalQueryContext.CommandLogger,
230-
_detailedErrorsEnabled));
226+
enumerator._relationalQueryContext.Connection,
227+
enumerator._relationalQueryContext.ParameterValues,
228+
enumerator._relationalCommandCache.ReaderColumns,
229+
enumerator._relationalQueryContext.Context,
230+
enumerator._relationalQueryContext.CommandLogger,
231+
enumerator._detailedErrorsEnabled));
231232

232-
_resultCoordinator = new SingleQueryResultCoordinator();
233+
enumerator._resultCoordinator = new SingleQueryResultCoordinator();
233234

234-
_relationalQueryContext.InitializeStateManager(_standAloneStateManager);
235+
enumerator._relationalQueryContext.InitializeStateManager(enumerator._standAloneStateManager);
235236

236-
return result;
237+
return false;
237238
}
238239

239240
public void Dispose()
@@ -289,7 +290,11 @@ public async ValueTask<bool> MoveNextAsync()
289290
if (_dataReader == null)
290291
{
291292
await _relationalQueryContext.ExecutionStrategyFactory.Create()
292-
.ExecuteAsync(true, InitializeReaderAsync, null, _relationalQueryContext.CancellationToken)
293+
.ExecuteAsync(
294+
this,
295+
(_, enumerator, cancellationToken) => InitializeReaderAsync(enumerator, cancellationToken),
296+
null,
297+
_relationalQueryContext.CancellationToken)
293298
.ConfigureAwait(false);
294299
}
295300

@@ -342,28 +347,29 @@ await _relationalQueryContext.ExecutionStrategyFactory.Create()
342347
}
343348
}
344349

345-
private async Task<bool> InitializeReaderAsync(DbContext _, bool result, CancellationToken cancellationToken)
350+
private static async Task<bool> InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
346351
{
347352
EntityFrameworkEventSource.Log.QueryExecuting();
348353

349-
var relationalCommand = _relationalCommandCache.GetRelationalCommand(_relationalQueryContext.ParameterValues);
354+
var relationalCommand = enumerator._relationalCommandCache.GetRelationalCommand(
355+
enumerator._relationalQueryContext.ParameterValues);
350356

351-
_dataReader = await relationalCommand.ExecuteReaderAsync(
357+
enumerator._dataReader = await relationalCommand.ExecuteReaderAsync(
352358
new RelationalCommandParameterObject(
353-
_relationalQueryContext.Connection,
354-
_relationalQueryContext.ParameterValues,
355-
_relationalCommandCache.ReaderColumns,
356-
_relationalQueryContext.Context,
357-
_relationalQueryContext.CommandLogger,
358-
_detailedErrorsEnabled),
359+
enumerator._relationalQueryContext.Connection,
360+
enumerator._relationalQueryContext.ParameterValues,
361+
enumerator._relationalCommandCache.ReaderColumns,
362+
enumerator._relationalQueryContext.Context,
363+
enumerator._relationalQueryContext.CommandLogger,
364+
enumerator._detailedErrorsEnabled),
359365
cancellationToken)
360366
.ConfigureAwait(false);
361367

362-
_resultCoordinator = new SingleQueryResultCoordinator();
368+
enumerator._resultCoordinator = new SingleQueryResultCoordinator();
363369

364-
_relationalQueryContext.InitializeStateManager(_standAloneStateManager);
370+
enumerator._relationalQueryContext.InitializeStateManager(enumerator._standAloneStateManager);
365371

366-
return result;
372+
return false;
367373
}
368374

369375
public ValueTask DisposeAsync()

src/EFCore.Relational/Query/Internal/SplitQueryingEnumerable.cs

+32-26
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ public bool MoveNext()
177177
_executionStrategy = _relationalQueryContext.ExecutionStrategyFactory.Create();
178178
}
179179

180-
_executionStrategy.Execute(true, InitializeReader, null);
180+
_executionStrategy.Execute(this, (_, enumerator) => InitializeReader(enumerator), null);
181181
}
182182

183183
var hasNext = _dataReader!.Read();
@@ -208,26 +208,27 @@ public bool MoveNext()
208208
}
209209
}
210210

211-
private bool InitializeReader(DbContext _, bool result)
211+
private static bool InitializeReader(Enumerator enumerator)
212212
{
213213
EntityFrameworkEventSource.Log.QueryExecuting();
214214

215-
var relationalCommand = _relationalCommandCache.GetRelationalCommand(_relationalQueryContext.ParameterValues);
215+
var relationalCommand = enumerator._relationalCommandCache.GetRelationalCommand(
216+
enumerator._relationalQueryContext.ParameterValues);
216217

217-
_dataReader = relationalCommand.ExecuteReader(
218+
enumerator._dataReader = relationalCommand.ExecuteReader(
218219
new RelationalCommandParameterObject(
219-
_relationalQueryContext.Connection,
220-
_relationalQueryContext.ParameterValues,
221-
_relationalCommandCache.ReaderColumns,
222-
_relationalQueryContext.Context,
223-
_relationalQueryContext.CommandLogger,
224-
_detailedErrorsEnabled));
220+
enumerator._relationalQueryContext.Connection,
221+
enumerator._relationalQueryContext.ParameterValues,
222+
enumerator._relationalCommandCache.ReaderColumns,
223+
enumerator._relationalQueryContext.Context,
224+
enumerator._relationalQueryContext.CommandLogger,
225+
enumerator._detailedErrorsEnabled));
225226

226-
_resultCoordinator = new SplitQueryResultCoordinator();
227+
enumerator._resultCoordinator = new SplitQueryResultCoordinator();
227228

228-
_relationalQueryContext.InitializeStateManager(_standAloneStateManager);
229+
enumerator._relationalQueryContext.InitializeStateManager(enumerator._standAloneStateManager);
229230

230-
return result;
231+
return false;
231232
}
232233

233234
public void Dispose()
@@ -303,7 +304,11 @@ public async ValueTask<bool> MoveNextAsync()
303304
}
304305

305306
await _executionStrategy.ExecuteAsync(
306-
true, InitializeReaderAsync, null, _relationalQueryContext.CancellationToken).ConfigureAwait(false);
307+
this,
308+
(_, enumerator, cancellationToken) => InitializeReaderAsync(enumerator, cancellationToken),
309+
null,
310+
_relationalQueryContext.CancellationToken)
311+
.ConfigureAwait(false);
307312
}
308313

309314
var hasNext = await _dataReader!.ReadAsync(_relationalQueryContext.CancellationToken).ConfigureAwait(false);
@@ -339,28 +344,29 @@ await _relatedDataLoaders(_relationalQueryContext, _executionStrategy!, _resultC
339344
}
340345
}
341346

342-
private async Task<bool> InitializeReaderAsync(DbContext _, bool result, CancellationToken cancellationToken)
347+
private static async Task<bool> InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
343348
{
344349
EntityFrameworkEventSource.Log.QueryExecuting();
345350

346-
var relationalCommand = _relationalCommandCache.GetRelationalCommand(_relationalQueryContext.ParameterValues);
351+
var relationalCommand = enumerator._relationalCommandCache.GetRelationalCommand(
352+
enumerator._relationalQueryContext.ParameterValues);
347353

348-
_dataReader = await relationalCommand.ExecuteReaderAsync(
354+
enumerator._dataReader = await relationalCommand.ExecuteReaderAsync(
349355
new RelationalCommandParameterObject(
350-
_relationalQueryContext.Connection,
351-
_relationalQueryContext.ParameterValues,
352-
_relationalCommandCache.ReaderColumns,
353-
_relationalQueryContext.Context,
354-
_relationalQueryContext.CommandLogger,
355-
_detailedErrorEnabled),
356+
enumerator._relationalQueryContext.Connection,
357+
enumerator._relationalQueryContext.ParameterValues,
358+
enumerator._relationalCommandCache.ReaderColumns,
359+
enumerator._relationalQueryContext.Context,
360+
enumerator._relationalQueryContext.CommandLogger,
361+
enumerator._detailedErrorEnabled),
356362
cancellationToken)
357363
.ConfigureAwait(false);
358364

359-
_resultCoordinator = new SplitQueryResultCoordinator();
365+
enumerator._resultCoordinator = new SplitQueryResultCoordinator();
360366

361-
_relationalQueryContext.InitializeStateManager(_standAloneStateManager);
367+
enumerator._relationalQueryContext.InitializeStateManager(enumerator._standAloneStateManager);
362368

363-
return result;
369+
return false;
364370
}
365371

366372
public async ValueTask DisposeAsync()

0 commit comments

Comments
 (0)