Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support named pipe connections #454

Closed
vaintroub opened this issue Mar 15, 2018 · 6 comments
Closed

Support named pipe connections #454

vaintroub opened this issue Mar 15, 2018 · 6 comments

Comments

@vaintroub
Copy link
Contributor

Named pipe connections on Windows are not supported. (Unlike e.g Unix domain socket connections, which are supported).
When implemented well (not like in C/NET, but e.g like in MariaDB's JDBC ), local named pipe connections can be a lot faster than TCP.

@bgrainger bgrainger changed the title Named pipe connections are not supported Support named pipe connections on Windows Mar 15, 2018
@bgrainger
Copy link
Member

When implemented well (not like in C/NET)

@vaintroub I'm not familiar with C/NET's implementation (I try to not look at their code) but am wondering what you consider the hallmarks of a "good" implementation?

I already have a transport layer that works over Stream; is using that with NamedPipeClientStream going to be good enough, or would more low-level operations be needed to get good performance?

@vaintroub
Copy link
Contributor Author

vaintroub commented Jun 7, 2018

Good is fast . I do not know why, but in C/NET pipe is substantially slower than TCP, and it should be maybe 1.´5-2x faster than local TCP connection, for simple queries like "do 1", or even slightly more complex ones like "select 1" . I think NamedPipeClientStream is going to do OK, but if you could benchmark this against TCP, you'll know more.

@bgrainger
Copy link
Member

bgrainger commented Jun 8, 2018

I've got some initial performance numbers back, and they're not great.

TCP

Method Mean
OpenFromPoolAsync 61.57 µs
OpenFromPoolSync 44.11 µs
ExecuteScalarAsync 112.51 µs
ExecuteScalarSync 85.40 µs
ReadBlobsAsync 178.99 µs
ReadBlobsSync 150.11 µs
ManyRowsAsync 803.64 µs
ManyRowsSync 752.27 µs

Named Pipe

Method Mean
OpenFromPoolAsync 180.8 µs
OpenFromPoolSync 155.5 µs
ExecuteScalarAsync 186.5 µs
ExecuteScalarSync 171.8 µs
ReadBlobsAsync 315.5 µs
ReadBlobsSync 332.5 µs
ManyRowsAsync 847.5 µs
ManyRowsSync 828.5 µs

OTOH, they're much better than MySql.Data 8.0.11:

MySql.Data 8.0.11 Named Pipe

Method Mean
OpenFromPoolAsync 431.5 µs
OpenFromPoolSync 441.5 µs
ExecuteScalarAsync 764.5 µs
ExecuteScalarSync 774.3 µs
ReadBlobsAsync 1,109.3 µs
ReadBlobsSync 1,093.1 µs
ManyRowsAsync 130,283.0 µs
ManyRowsSync 133,221.1 µs

I'd love to benchmark local TCP/IP connections with SIO_LOOPBACK_FAST_PATH enabled; that might be the best way to get high-performance local communication on Windows. (But I assume that would require building a custom version of MySQL Server.)

This shipped in 0.41.0 with these performance numbers. I can potentially revisit it in the future based on user feedback.

@bgrainger bgrainger changed the title Support named pipe connections on Windows Support named pipe connections Jun 8, 2018
@vaintroub
Copy link
Contributor Author

vaintroub commented Jun 8, 2018

I doubt that any TCP (even with FAST path) is better than named pipe. Can you share your code?
MariaDBs JDBC is substantially faster via named pipe, as is native C connector. IIRC, JDBC is using BufferedStream for input (but not output). Also, the pipe name is important , \\.\pipename is much better than \\hostname\pipename

@bgrainger
Copy link
Member

Named pipe is opened in this function:

private Task<bool> OpenNamedPipeAsync(ConnectionSettings cs, IOBehavior ioBehavior, CancellationToken cancellationToken)

Reading/writing the stream happens here: https://github.com/mysql-net/MySqlConnector/blob/dce98defdffaf8ccffb4b795187157d096e13f17/src/MySqlConnector/Protocol/Serialization/StreamByteHandler.cs

I/O is buffered here: https://github.com/mysql-net/MySqlConnector/blob/dce98defdffaf8ccffb4b795187157d096e13f17/src/MySqlConnector/Protocol/Serialization/BufferedByteReader.cs

. is used as the host name if possible:

HostNames = (csb.Server == "." || string.Equals(csb.Server, "localhost", StringComparison.OrdinalIgnoreCase)) ? s_localhostPipeServer : new[] { csb.Server };

Does the JDBC driver use a "stream" abstraction, just talk directly to the Win32 API, something else?

@vaintroub
Copy link
Contributor Author

JDBC uses java.io.RandomAccessFile for reading and writing ( but it extends Socket , because this is how different transports are implemented in this driver).
https://github.com/MariaDB/mariadb-connector-j/blob/master/src/main/java/org/mariadb/jdbc/internal/io/socket/NamedPipeSocket.java

It uses native code, only for "busy pipe" workaround (Java would throw FileNotFoundException on many concurrent connect requests). If native code is not possible, there is just retry after some sleep.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

2 participants