Skip to content

Cache tags from DbCommand#774

Merged
kevingosse merged 5 commits into
masterfrom
kevin/dbcommandtags
Jul 2, 2020
Merged

Cache tags from DbCommand#774
kevingosse merged 5 commits into
masterfrom
kevin/dbcommandtags

Conversation

@kevingosse

Copy link
Copy Markdown
Contributor

Parsing the connection string is a costly operation that we do at every query, even though we can reasonably expect users to have a limited set of connection strings.

Benchmark:

// With connection string: Server=myServerName,myPortNumber;Database=myDataBase;User Id=myUsername;Password=myPassword;
SpanExtensions.AddTagsFromDbCommand(span, dbCommand);
BenchmarkDotNet=v0.12.0, OS=Windows 10.0.19041
Intel Core i7-9750H CPU 2.60GHz, 1 CPU, 12 logical and 6 physical cores
  [Host]     : .NET Framework 4.8 (4.8.4180.0), X64 RyuJIT
  Job-VTGAFA : .NET Framework 4.8 (4.8.4180.0), X64 RyuJIT
  Job-MNUBEA : .NET Core 3.1.5 (CoreCLR 4.700.20.26901, CoreFX 4.700.20.27001), X64 RyuJIT

Method Runtime Mean Error StdDev Ratio Gen 0 Gen 1 Gen 2 Allocated
Old .NET 4.7.2 4,336.9 ns 49.97 ns 44.30 ns 1.00 0.3433 - - 2182 B
New .NET 4.7.2 242.4 ns 1.54 ns 1.45 ns 0.06 - - - -
Old .NET Core 3.1 3,495.5 ns 12.84 ns 10.02 ns 1.00 0.3510 - - 2208 B
New .NET Core 3.1 236.4 ns 3.97 ns 3.52 ns 0.07 - - - -

@kevingosse

Copy link
Copy Markdown
Contributor Author

2 things to take care of before merging:

  • This would cause a memory leak if there's some random part in a connection string. I can't think of a situation where that would happen, but I'm going to do some research to make sure
  • I'll add a unit test

@kevingosse

Copy link
Copy Markdown
Contributor Author

I could think of a situation where we would have an infinite number of connection strings: if the user opens arbitrary Excel files with ADO.NET. This is very unlikely but still possible, so I added a fail-safe mechanism. There's no noticeable impact on the benchmark (expected, since the fast path doesn't change).

BenchmarkDotNet=v0.12.0, OS=Windows 10.0.19041
Intel Core i7-9750H CPU 2.60GHz, 1 CPU, 12 logical and 6 physical cores
  [Host]     : .NET Framework 4.8 (4.8.4180.0), X64 RyuJIT
  Job-VTGAFA : .NET Framework 4.8 (4.8.4180.0), X64 RyuJIT
  Job-MNUBEA : .NET Core 3.1.5 (CoreCLR 4.700.20.26901, CoreFX 4.700.20.27001), X64 RyuJIT

Method Runtime Mean Error StdDev Ratio Gen 0 Gen 1 Gen 2 Allocated
Old .NET 4.7.2 4,464.6 ns 72.36 ns 67.69 ns 1.00 0.3433 - - 2182 B
New .NET 4.7.2 244.2 ns 4.59 ns 4.50 ns 0.05 - - - -
Old .NET Core 3.1 3,711.8 ns 73.20 ns 78.33 ns 1.00 0.3510 - - 2208 B
New .NET Core 3.1 242.2 ns 2.32 ns 1.94 ns 0.07 - - - -

@kevingosse
kevingosse marked this pull request as ready for review July 1, 2020 11:16
@kevingosse
kevingosse requested a review from a team as a code owner July 1, 2020 11:16

@lucaspimentel lucaspimentel left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Left a non-blocking question to satisfy my curiosity.

{
// Populating the cache. This path should be hit only during application warmup
// ReSharper disable once ConvertClosureToMethodGroup -- Lambdas are cached by the compiler
return cache.GetOrAdd(connectionString, cs => ExtractTagsFromConnectionString(cs));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just curious, is the "Resharper disable" comment just to avoid writing it like this? If so, is there a performance reason for this, or just cosmetic?

Suggested change
return cache.GetOrAdd(connectionString, cs => ExtractTagsFromConnectionString(cs));
return cache.GetOrAdd(connectionString, ExtractTagsFromConnectionString);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the comment is there to prevent Resharper from rewriting into a method group. The delegate is cached when using lambdas but not when using method groups, so that would cause an additional heap allocation at each call.
dotnet/roslyn#5835

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL. Thanks!

@kevingosse
kevingosse merged commit 382ea15 into master Jul 2, 2020
@kevingosse
kevingosse deleted the kevin/dbcommandtags branch July 2, 2020 08:52
@zacharycmontoya zacharycmontoya added this to the 1.18.2 milestone Jul 9, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants