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

Optimize startup time using TCP sockets instead of junixsocket and tput instead of jline #4009

Merged
merged 14 commits into from
Nov 23, 2024

Conversation

lihaoyi
Copy link
Member

@lihaoyi lihaoyi commented Nov 22, 2024

The AFUNIXServerSocket library we are using seems to cause an extra ~500ms latency launching the Mill client, and also causes the Graal native-image to crash during generation.

  • Using TCP sockets seems to cut the launch overhead down from ~1000ms to ~500ms, and opens up the possibility of using native-image to cut it further.

  • Using localhost TCP sockets seems secure as far as I can tell https://security.stackexchange.com/questions/108544/once-established-are-sockets-on-localhost-secure

  • The JVM also ships with UnixDomainSocketAddress starting from JDK 17 that we can consider using, either by requiring JDK17 or by conditionally using it based on JDK version. But for now I want to keep supporting JDK11 and don't want to split the code paths, so we'll hold off on this for now

jline.terminal.Terminal.getSize also adds a few hundred milliseconds, so we instead use the same tput command that Ammonite uses which takes <10ms.

  • On windows where tput isn't support, it falls back to 100 cols, which I reduced it down from 120 to hopefully avoid line wrapping in most terminals while still providing a decent experience

Together these two changes cuts down the time taken for a hot time ./mill version on the Mill repo from ~1.05s to ~0.24s

@lihaoyi lihaoyi changed the title Swap back to TCP sockets for server-client communication Optimize startup time using TCP sockets and tput instead of jline Nov 22, 2024
@lihaoyi lihaoyi changed the title Optimize startup time using TCP sockets and tput instead of jline Optimize startup time using TCP sockets instead of junixsocket and tput instead of jline Nov 22, 2024
@@ -48,7 +46,8 @@ abstract class Server[T](

while (
running && {
val serverSocket = bindSocket()
val serverSocket = new java.net.ServerSocket(0)
Copy link

@roman-mibex-2 roman-mibex-2 Nov 22, 2024

Choose a reason for hiding this comment

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

This binds to 0.0.0.0 for me, so it is listening to the world, including external network. At least on my machine.

So, better IMO:

        val serverSocket = new java.net.ServerSocket()
        serverSocket.bind(new java.net.InetSocketAddress("127.0.0.1",0))

I suggesting the IP 127.0.0.1 over 'localhost', because localhost sometimes resolves to IP6 vs IP4, creating odd miss-matches.

Copy link
Member Author

Choose a reason for hiding this comment

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

Looks like I forgot to pass in the host entirely, but yeah I can use 127.0.0.1

long retryStart = System.currentTimeMillis();
Socket ioSocket = null;
Throwable socketThrowable = null;
while (ioSocket == null && System.currentTimeMillis() - retryStart < serverInitWaitMillis) {
try {
ioSocket = AFUNIXSocket.connectTo(addr);
int port = Integer.parseInt(Files.readString(serverDir.resolve(ServerFiles.socketPort)));
ioSocket = new java.net.Socket("localhost", port);

Choose a reason for hiding this comment

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

I recommend '127.0.0.1' over localhost. I had multiple times where using 'localhost' gives mixups between IP4 and IP6.
Like one process resolves it to IP4 and the other process to IP6 and then they fail to connect each other.

Or cases where resolving localhost added extra mill-seconds for weird reasons.

@lihaoyi lihaoyi marked this pull request as ready for review November 22, 2024 10:45
catch { case e: FileAlreadyExistsException => /* someone else already did this */}
catch {
case e: FileAlreadyExistsException => /* someone else already did this */
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

@lihaoyi this file also got same changes in my PR while fixing linting error should i remove the changes from there or rebasing and merge will automatically fix this

@lihaoyi lihaoyi merged commit b1f6be0 into com-lihaoyi:main Nov 23, 2024
25 of 27 checks passed
@lefou lefou added this to the 0.12.3 milestone Nov 23, 2024
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.

4 participants