Skip to content

Improve async performance #164

@bgrainger

Description

@bgrainger

I have a (non-public) test case that executes two bulk read queries (in a batch); one that returns 31K rows of int,string,int,int and a second that returns 37K rows of int,int,int,int. The remote server is MySQL 5.6 on Linux, about 10ms away from my test box.

On full .NET 4.6.2 on Windows 10, the sync codepath uses less than one core and completes in 4s; the async code path uses over 300% CPU and takes 20s wall time.

sync:
real   4.043s
total  1.922s
user   1.438s
sys    0.484s

async:
real   20.840s
total  68.422s
user   47.531s
sys    20.891s

With dotnet, the results are even worse:

sync:
real   4.336s
total  1.953s
user   1.469s
sys    0.484s

async:
real   24.468s
total  85.703s
user   59.219s
sys    26.484s

Some investigation with dotTrace and dotPeek on the full .NET Framework shows that Socket.ReceiveAsync (used in the async code path) takes 2s of CPU time while Socket.Receive (which blocks until the data is received) only takes 1.5s. Moreover, Socket.ReceiveAsync appears to only return false (i.e., receive completed synchronously) on failure; a successful result always completes asynchronously, meaning that we suffer the penalty of a callback being queued to the threadpool on top of the extra CPU time just to initiate the operation!

Additionally, network bandwidth (shown in Task Manager) is noticeably lower for the async case than the sync case.

We may need to find some way to get the benefits of asynchronous I/O without the overhead of Socket.ReceiveAsync, perhaps by #163 or by writing custom P/Invoke for the full .NET Framework on Windows.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels
    No fields configured for Feature.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions