How to achieve maximum single threaded performance?

I’m planning on making a minecraft server for some friends. But I feel like going ridiculously overkill with it. Should be for 8-16 people. It just seems like a fun project.

What would be a good CPU to get for maximum single threaded performance? Minecraft servers only run one the one thread. I’m wondering if turning off some cores will increase the thermal capacity for additional overclocking?

I will need more than 1 thread though, since I think I’ll do LZ4 compression with btrfs for better IO performance, and also the operating system is a thing.

Would overclocking memory be worth it? Even for a Ryzen system? I honestly think I should just buy faster memory and not bother because I imagine there would be some instability.

What about channels? am I better filling out every slot and going quad channel or something?

Sorry that there’s a lot of little questions. I am thinking about a lot right now.

Not sure how LZ4 would improve IO performance given the extra memory copies and CPU overhead each read or write creates. Having an SSD is all you need, from my experience a MC server does only little IO once running.

Minecraft servers are threaded to some extend especially in chunk generation, loading etc as well as connections btw but particularly modpacks harm the threading. Having more cores does help, and to make a server smooth I prefer tweaking the JVM GC a little.

I would worry less about memory speeds and configs as your performance gains are usually rather small compared to just going with much better platform. I’d say 8GB system RAM are minimum, 16GB better for modpack servers. An eightcore CPU wouod be cool.

If you want to measure performance characteristics yourself try benchmarking a server on your current PC to find patterns rather than making assumptions.

In terms of compression being faster. Here’s a video from Level1Linux.
Or if you don’t want to hear the whole explanation:
But it’s something I’m gonna test anyway. It’s possible that minecraft world files don’t compress well under lz4.

I wasn’t aware that 1.14 introduced async multithreading for some chunk operations but it seems primarily still single threaded. Though that might be different for things like papermc. I will test

I would worry less about memory speeds and configs as your performance gains are usually rather small compared to just going with much better platform.

Memory speeds is more because i’m likely to go ryzen and benchmarks seem to show a decent performance hit for low speed ram.
For java argument’s yeah, apart from -XX:MaxGCPauseMillis=50 I don’t find much benefit from them (from my own testing).

Surprisingly I forgot about GC being multithreaded. I should remember because I have spent so much time with java. But yeah I will keep that in mind.

As for more RAM, yeah for vanilla you don’t need a whole lot. If you don’t have enough and the server has to run GC to free some often you have issues.

I’m definitely going to benchmark, but my question was primarily for overclocking and getting high single threaded performance. I wanted to know if more thermal capacity would let me do so by disabling threads.

Interesting. But I’m not sure if MC is that IO dependent, I ran a nice modpack server off an HDD a long time a while ago. Linux VFS should take care of it.

even before they did that and I wasn’t aware either, it uses your other threads a bunch too as the trashing of the heap makes the GC busy

Perhaps the default GC was improved. With no GC config and the pause interval you can easily get a seriously stuttery server when exploring a huge cage complex, I remember. Enemies would pause and teleport making it a lot harder to fight them. A good benchmark I’d say. For OpenJDK8 I used something like this: -server -XX:MaxGCPauseMillis=50 -XX:+DisableExplicitGC -XX:+UseG1GC

Apart from disabling SMT benefitting singlethread performance, I am not sure. I thought idle cores lead to more power available for busy cores.

Anyway wish you success in building that server.

There was this 40 core Xeon we had here and it’s highest turbo bin topped out at 20 cores, which is also what time spy tops out at, so after disabling 20 of the 40 cores and hyperthreading we almost hit top 10

So disabling cores can make it permanently turbo higher
And disabling SMT and HT might be worth experimenting with in single threaded situations


App is CPU-L

I’m using java 16 so that might be the discrepency.

Thank you sir I appreciate it.

I will take a look at these thank you.

If you’re going Ryzen I’d hesitate before disabling cores as I’m pretty sure Ryzen scheduler will bounce single threaded workloads from core to core (possibly to balance heat).

There’s support for zstd these days, it’s supposed to be better than lz4 on average.

If storage latency is a concern - and you have enough ram - it’s technically possible to create a ramdisk e.g. using zram, with e.g. btrfs on top; and then use the incremental snapshot backup feature to periodically save state every 5 minutes onto stable storage. With one more explicit sync on shutdown and restore on startup and it’ll be great - you’ll probably never lose state except on forceful shutdown you’d just rollback the clock by up to 5 minutes. Probably you wouldn’t even need an SSD - but it’d be nice to have one anyway and of course you’ll need some ram instead.

It definitely seems to on my 8 core. Hmm, this might be a concern. I will test thermals pretty throughly since I’m going to overclock but maybe it spreading out heat with the extra cores will let it improve performance. I don’t know.

Woha really? do you have any links on how to do this. It sounds amazing.

No sorry. OTOH you’d probably want to make some small shell scripts with a couple of commands each to try things out, and then use later as well:

initial_restore.sh (that runs on every startup)
incremental_backup.sh (that call on shutdown as well as from a timer)

later you can wire these in as systemd services/timers

Initial setup (also on every startup) that would get you an empty filesystem in ram first:

$ modprobe zram
$ echo 8G > /sys/block/zram0/disksize
$ mkfs.btrfs /dev/zram0
$ mkdir -p /mnt/ram_stuff
$ mount /dev/zram0 /mnt/ram_stuff

Then as a once off you’d create your subvolume for your “forever” data, in ram, and the first ever initial snapshot that you’ll backup fully (not incrementally). In the future you’d be restoring this subvolume from a backup

$ btrfs subvolume create /mnt/ram_stuff/data
$ echo "hello world $(date)" | tee /mnt/ram_stuff/data/hello.txt # ..write some stuff
$ # make a first snapshot
$ btrfs subvolume snapshot -r /mnt/ram_stuff/data /mnt/ram_stuff/snapshots.1
$ # ... send the first snapshot to a more permanent btrfs home that's not in ram
$ # assumes /data is on btrfs
$ btrfs send /mnt/ram_stuff/snapshots.1 | btrfs receive /data/backups/from_ram_stuff/

… now you’ve done the initial backup…from here on, you make new snapshots but send and receive incrementals which look like

$ echo "hello $(date)" | tee /mnt/ram_stuff/data/hello.again.txt # pretend we've changed stuff
$ btrfs subvolume snapshot -r /mnt/ram_stuff/data /mnt/ram_stuff/snapshot.2
$ # send the delta between two snapshots to /data
$ btrfs send -p /mnt/ram_stuff/snapshot.1 /mnt/ram_stuff/snapshot.2 | btrfs receive /data/backups/from_ram_stuff/

You can repeat the incremental stuff as many times as you like, but you’ll need to increment the snapshot counter, keep making new snapshots.

How do you restore? Pick the latest snapshot and send it back into empty btrfs in ram, then snapshot that without -r which stands for readonly, to make it read-write.

$ btrfs send /data/from_ram_stuff/snapshot.2 | btrfs receive /mnt/ram_stuff/snapshot.2
$ btrfs subvolume snapshot /mnt/ram_stuff/snapshot.2 /mnt/ram_stuff/data

something along those lines. There’s plenty of docs to get the syntax right in:

https://www.kernel.org/doc/Documentation/blockdev/zram.txt
https://manpages.debian.org/testing/btrfs-progs/btrfs-subvolume.8.en.html

and you’ll need to be able to identify “the latest snapshot” using something like LATEST=$(ls -tr /mnt/ram_stuff/snapshot.* | head -n1 | cut -d. -f2) and then do things like NEXT=$(($LATEST +1)) … probably.

also I’m not sure what happens if you have a power cut mid way, and have half a snapshot, obviously you don’t want to restore from that on startup - I forgot if you can end up with partial snapshots or not.

Who knows maybe this helps it could be pointless. It probably doesn’t hurt to try and it just boils down to doing backups and restores.

2 Likes

This topic was automatically closed 273 days after the last reply. New replies are no longer allowed.