Skip to content

Network optimization with sendmmsg (part 3)#204

Draft
BalaM314 wants to merge 3 commits into
Anuken:masterfrom
BalaM314:syscall-shenanigans
Draft

Network optimization with sendmmsg (part 3)#204
BalaM314 wants to merge 3 commits into
Anuken:masterfrom
BalaM314:syscall-shenanigans

Conversation

@BalaM314

Copy link
Copy Markdown
Contributor

Use sendmmsg syscall directly instead of sending UDP data to each connection.

Currently, UDP data that needs to be sent to all connections (like entity snapshots) is sent by serializing once, compressing once, then calling DatagramSocket.send() on each individual connection. This results in O(pe) syscalls. With the volume of data being sent, syscall overhead is significant. There also may be some overhead on each call going through the JVM classes, according to my flame graphs.

The sendmmsg syscall allows sending multiple UDP messages with one syscall. We call this through Java FFM, cutting a factor of p in the number of syscalls.

this is still very much a prototype, but it's a functional prototype (uploaded to fish servers and we're seeing a performance improvement). It's probably at least a little broken and unsafe.

Caveats:

  • The performance improvement may be simply due to dropped packets. I saw something about throwing errors in the patched flame graph, which is odd because I didn't see any errors in console. I need to measure the packet rate and make sure it's still sending all the packets it should. I wasn't able to test the snapshot reception rate on my end because my network connection is quite bad and can't handle 30 players x 3000 units.
  • Test was conducted with 30 players on the same dest IP (I don't have a botnet) and one player on another IP.
  • The code is still a prototype, there's several TODOs that need to be addressed. I have zero experience with Java FFM, there is probably a cleaner way to write it.

BalaM314 added 3 commits July 14, 2026 12:41
Requires Java 25 for FFM support. Only works on Linux. The old
implementation will be used otherwise.
@BalaM314 BalaM314 changed the title Syscall shenanigans Network optimization with sendmmsg (part 3) Jul 14, 2026
@BalaM314

Copy link
Copy Markdown
Contributor Author

Flame graphs:

patched, unpatched, patched-2, unpatched-2 were taken back to back in the same world, toggling the optimization on and off. We had ~3000 units (mostly 1000 each of dagger, mace, crawler) and 30 players. (We see similar numbers in real gameplay, for example in the map The Rift) There was also a bunch of smites running to generate artificial lag.
patched-3 and unpatched-3 were on the same map but with the smites disabled.

profiles.zip

Comment thread build.gradle
java{
sourceCompatibility = 1.8
targetCompatibility = 1.8
sourceCompatibility = JavaVersion.VERSION_25

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This is a complete non-starter; targeting 25 breaks compilation for Android, iOS and desktop. You will need to find some way to optionally load the 25-target code without changing the main build script or target.

ArcNet.handleError(e);
con.close(DcReason.error);
}
} else {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Lots of incorrect formatting in the PR (extra spaces everywhere)

public void bind(InetSocketAddress tcpPort, InetSocketAddress udpPort) throws IOException{
close();
try {
multi = new MultiUdpSender();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Should be gated behind OS.javaVersion >= 25

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.

2 participants