MySqlConnector icon indicating copy to clipboard operation
MySqlConnector copied to clipboard

Implement optimised MySqlDataReader.GetX methods

Open bgrainger opened this issue 6 years ago • 4 comments
trafficstars

MySqlDataReader.GetInt32(int ordinal) is essentially implemented as return (int) GetValue(ordinal);

This boxes the int as an object then unboxes it. It would be more efficient to return the int value directly and would eliminate allocations. (Coupled with 00199a0248bf436dd77e3f517d12a8fde2678d63 this would also optimise GetFieldValue<int>.)

For the text protocol, it might be possible to implement this without significant code duplication if each GetX method just needs to check for an integral column type, parse the text, and check for overflow.

A quick-and-dirty implementation yielded the following benchmark results:

.NET Core 3.0:

Method Mean Error StdDev Median Gen 0 Gen 1 Gen 2 Allocated
GetInt32 21.21 ns 0.4360 ns 0.6112 ns 21.06 ns - - - -
GetValue 30.96 ns 0.7450 ns 1.4878 ns 30.56 ns 0.0051 - - 24 B
GetFieldValue 26.04 ns 0.5446 ns 1.0228 ns 25.57 ns - - - -

Before, GetInt32 and GetFieldValue<int> were 31-37ns and also allocating.

.NET 4.8

Method Mean Error StdDev Gen 0 Gen 1 Gen 2 Allocated
GetInt32 54.19 ns 1.0760 ns 1.1513 ns - - - -
GetValue 57.13 ns 1.1467 ns 1.6076 ns 0.0050 0.0001 - 24 B

The improvement is less pronounced here, with the method taking ~59ns before the change.

bgrainger avatar Oct 20 '19 05:10 bgrainger

Optimising GetInt32 specifically would be useful for the TechEmpower Framework Benchmarks: https://github.com/TechEmpower/FrameworkBenchmarks/blob/a94705893dd6a0e7e8312c79d0e4dff7ba8eb990/frameworks/CSharp/aspnetcore/PlatformBenchmarks/Data/RawDb.cs#L49-L50

bgrainger avatar Oct 20 '19 05:10 bgrainger

For the text protocol, it might be possible to implement this without significant code duplication if each GetX method just needs to check for an integral column type, parse the text, and check for overflow.

It looks like naively extending the current code might result in quite a bit of duplication and potential inconsistency between different access methods. A different approach may be needed.

bgrainger avatar Oct 21 '19 03:10 bgrainger

Another related optimization, could be the ability to access the buffer of the reader, to be able to use JsonSerializer.DeserializeAsync<JsonDocument> directly on the buffer of the reader.

ugavnholt avatar Jun 15 '20 12:06 ugavnholt

access the buffer of the reader

If I understand correctly, that sounds like https://github.com/dotnet/runtime/issues/24899. The current best workaround is to call GetStream, which will return a MemoryStream that reads directly from the buffer (https://github.com/mysql-net/MySqlConnector/issues/592).

bgrainger avatar Jun 15 '20 15:06 bgrainger