txdv / MySqlSharp

Extremely Fast MySQL Driver for C#, work in progress.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

MySqlSharp

Extremely Fast MySQL Driver for C#, work in progress.

Async does not mean fast, I thought database driver is the serialization problem over TCP. I've released two fastest serializers ZeroFormatter and MessagePack for C#, this MySQL driver is using there optimization techiniques.

image

It shows 1/50 memory usage decrease(not optimized yet, I should reduce means perfs)

Currently this driver is under development and is not filled with alpha version. However, I am glad if there is your attention and opinion.

How achive performance?

  • Async over Sync, Sync over Async, both slows. We should implementes optimized for both.
  • Use Mutable Struct Reader, it enables reduce memory allocation.
  • Direct deserialize from binary to number.
  • Avoid ADO.NET abstrtaction, expose primitive api and ADO.NET should be built on top of it.
  • Micro ORM(like Dapper) built on top of primitive MySQL API.
  • Fast query text parsing deliver with ref char[] buffer(don't use StringBuilder and String) - FastQueryParser.
  • Use prepared-statement cache like Npgsql approach.

MySQL X-Protocol increase server-client performance but Amazon Aurora or others can not use X-Protocol yet.

Mutable Struct Reader

MySQL protocol stream has many chunked packets. If you make(or as MySQLConnecto does) packet reader, requires many reader allocation.

image

I've implements struct packet reader and static helper methods.

// Standard API, I don't use it
using (var packetReader = new PacketReader())
using (var protocolReader = new ProtocolReader(packetReader))
{
    protocolReader.ReadTextResultSet();
}

// Mutable Struct Reader
var reader = new PacketReader(); // struct but mutable, has reading(offset) state
ProtocolReader.ReadTextResultSet(ref reader); // (ref PacketReader)

It reduce many memory allocations.

Direct deserialize from binary to number

MySQL row data is normaly text protocol. If retrieve integer, requires string encoding and parsing.

// string allocation and parsing cost
int.Parse(Encoding.UTF8.GetString(binary));

I've introduced NumberConverter it enables direct convert.

public static Int32 ToInt32(byte[] bytes, int offset, int count)
{
    // Min: -2147483648
    // Max: 2147483647
    // Digits: 10

    if (bytes[offset] != Minus)
    {
        switch (count)
        {
            case 1:
                return (System.Int32)(((Int32)(bytes[offset] - Zero)));
            case 2:
                return (System.Int32)(((Int32)(bytes[offset] - Zero) * 10) + ((Int32)(bytes[offset + 1] - Zero)));
            case 3:
                return (System.Int32)(((Int32)(bytes[offset] - Zero) * 100) + ((Int32)(bytes[offset + 1] - Zero) * 10) + ((Int32)(bytes[offset + 2] - Zero)));
            // snip case 4..9
            case 10:
                return (System.Int32)(((Int32)(bytes[offset] - Zero) * 1000000000) + ((Int32)(bytes[offset + 1] - Zero) * 100000000) + ((Int32)(bytes[offset + 2] - Zero) * 10000000) + ((Int32)(bytes[offset + 3] - Zero) * 1000000) + ((Int32)(bytes[offset + 4] - Zero) * 100000) + ((Int32)(bytes[offset + 5] - Zero) * 10000) + ((Int32)(bytes[offset + 6] - Zero) * 1000) + ((Int32)(bytes[offset + 7] - Zero) * 100) + ((Int32)(bytes[offset + 8] - Zero) * 10) + ((Int32)(bytes[offset + 9] - Zero)));
            default:
                throw new ArgumentException("Int32 out of range count");
        }
    }
    else
    {
        // snip... * -1
    }
}

Primitive API for MySQL

Expose MySQL Protocol(COM_QUIT, COM_QUERY, COM_PING, etc...) directly.

// Driver Direct
var driver = new MySqlDriver(option);
driver.Open();

var reader = driver.Query("selct 1"); // COM_QUERY
while (reader.Read())
{
    var v = reader.GetInt32(0);
}

// you can use other native APIs
driver.Ping(); // COM_PING
driver.Statistics(); // COM_STATISTICS

Of course, you can also use ADO.NET.

// ADO.NET Wrapper
var conn = new MySqlConnection("connStr");
conn.Open();

var cmd = conn.CreateCommand();
cmd.CommandText = "select 1";

var reader = cmd.ExecuteReader();
while (reader.Read())
{
    var v = reader.GetInt32(0);
}

About

Extremely Fast MySQL Driver for C#, work in progress.

License:MIT License


Languages

Language:C# 100.0%