SwitchNet - A blazingly fast and easy to use networking module for reducing bandwidth and overhead across remotes

Heyo! I have released yet another new networking module.

SwitchNet is a blazingly fast networking module for reducing bandwidth and overhead across remotes, and is also designed to be extremely easy to use.

It also implements some security features to further protect against attacks.

It is buffer-based to achieve the custom compression of values resulting in reduced bandwidth, and also has per frame batched replication to help reduce remote overhead of requests, and supports all three remote types:

  • RemoteEvent
  • UnreliableRemoteEvent
  • RemoteFunction

This library is licensed under the MIT license.

Installation

To install, you can install via. Wally, or via the latest release on the GitHub.

Documentation

Documentation + other info can be found on the GitHub.

Bandwidth reduction

With an outgoing stream from Client → Server with a payload being sent to the server at a rate of 10Hz, these were the data figures i got using the following payload:

local Copies = 4000
local Object = {
	Size = vector.create(53, 55, 89.62),
	CFrame = CFrame.new(39.225, 31.1, 531.643) * CFrame.fromEulerAnglesXYZ(math.rad(90), math.rad(15), math.rad(155)),
	Disabled = false,
	Floating = false,

	Metadata = {
		Name = "I am John.",
		ClientAge = os.clock(),
		Timestamps = { os.time(), os.time(os.date("*t")) },

		ExtraMetadata = {
			__TAG = "TagName...I think? Idk",
			__ATT = "__ID",
			__EXTRA_ATTS = { "__META_ID", "__MISC_ID" },
		}, 
	},

	Info = TweenInfo.new(0.5, Enum.EasingStyle.Quad, Enum.EasingDirection.InOut),
	CK = FloatCurveKey.new(0.1, Enum.KeyInterpolationMode.Linear),
	Date = DateTime.now(),
}

local Payload = table.create(Copies, Object)

Average data rate sent after ~30 seconds of the test running:

Remote type Avg. Outgoing data rate
SwitchNet remote ~5.98KB/s
Raw remote ~9569.61KB/s

These results were gathered using version v0.2.5.
Roblox also natively compresses buffers when they are sent over remote events, which is what allows the data rate to get this low.

The data rate will obviously depend on whatever the data you are sending is, but we are already seeing great results.

CPU efficiency

SwitchNet implements loads of optimizations to ensure that there is minimal CPU usage being wasted. Even with a non-strictly typed network library, it can achieve pretty good speeds.

Some pros and cons

While i do believe this is a decent resource especially for less experienced programmers, there is still some things to address.

Pros

  • Simple-to-use API + readable codebase
  • Less performance compromise of having a non-strictly typed structure
  • More friendly towards less experienced developers looking to just reduce bandwidth

Cons

  • Won’t allow you to define exactly how a packet is compressed, which can result in bandwidth bloat (due to lack of strictly-typed structures, e.g. every plain number is sent over as a float64 still)
  • Might not be very suitable for more advanced games/systems that rely much more on more powerful micro-optimizations/organizing using schemas/type structures

If you are an advanced developer who is more-so leaning towards prioritizing micro optimizations/schema structures/other more advanced control features for your games/systems, then this library probably won’t be as suitable.

But if you are a developer looking for a simple system that is quick and easy to add, and more focused on at least optimizing your remotes significantly, this is a great choice.

Final summary

If you do check this out or even use it, i would love to hear your feedback on how i could improve this even more, or if you run into any bugs/other issues.

Thanks for checking this out! I hope this is a useful resource for some developers. :+1:

12 Likes

I have given the post an update which outlines extra details, including bandwidth reduction + CPU benchmark figures!

v0.1.0

  • Gutted out ByteBuffer and moved more core reading/writing logic to each type module, This has reduced function calls quite significantly and a 33% CPU efficiency boost as a result
  • Fixed EnumItem not reading correctly (pointer would offset 15)
  • Removed types Path2DControlPoint, PathWaypoint and PhysicalProperties
2 Likes

Any reason why I should use this over packet?

1 Like

If you are after simplicity without compromise of performance then SwitchNet is a solid choice IMO, if you’re after more strictly typed libraries then Packet or ByteNet are solid options
I may consider adding strict type systems in SwitchNet eventually too, so you can compress certain values more (e.g. uint32 instead of a float64 for an int only number)

v0.1.1

  • Fixed Color3 reading incorrectly (constructor was .new instead of .fromRGB, oops)
  • Fixed CFrame writing incorrectly with complex angle sets
1 Like

v0.1.2

  • Fixed CFrame rotations (again, apologies!)

I have also added a lossless bool toggle inside the CFrame type module, if you ever run into issues, you can enable it

1 Like

v0.1.3

  • Fixes NumberRange offsetting incorrectly for reading & writing
  • Fixes UDim2 offsetting incorrectly for reading

Im confused, because this does utilize the features you mentioned. Did you properly look at the code when reviewing it?

for reference, all the buffering related logic is in Bitstream, and the remote request batching is handled in Server + Client

If you’re going to be using defined types for Networking, then you should use Blink or zap over packet, but this module is non-strictly defined typed networking, so it’s more user-friendly while still having better performance than standard

dexter-gross

…can you explain why?

this is entirely a downside


overall… no reason to use this resource? educate me

1 Like

Blink and zap are comparable in performance (I’d say Blink is probably slightly better), and they both are better then packet

I have noticed some pretty significant performance drops tables being serialized, i am now working on improving it

v0.2.0

  • Fully removed ByteBuffer class (wasn’t needed)

As a result, all types writing/reading should now also be much more efficient as there is less referencing being done

  • Did some optimizations to main read + write performance of Bitstream

Bitstream.Create no longer uses varadic arguments, and just directly receives an array
Bitstream.Create now has a 2nd parameter for buffer size, so it can be calculated pre-compression instead
Gutted out type storing on write to save some memory
Made references use an .n based array instead

  • Fixed complex nested tables with external references having incorrectly offset pointers, causing data loss
  • Improved the performance of tables reading + writing
  • Fixed string writer writing a uint16 instead of a uint32 for size pointer
  • Fixed FloatCurveKey writing left and right tangents with non-cubic interpolation modes (Will help save bandwidth too)
  • Increased buffer size limit to 2 ^ 21 bytes

v0.2.1

  • Removed ReferencesCount from each NetworkPacket (it wasn’t needed)
  • Added some more remote typechecking measures
  • Other minor improvements

v0.2.2

  • Removed micro profiler tags from remote function handlers
  • Restructured server replication handler
  • Minor performance improvements

v0.2.3

  • Restructured client replication handler (forgot to do that previous patch)

v0.2.4

  • Slight improvements to remote verification on both server and client
  • Fixed a type flaw on client where the player argument was still present
  • Slight improvements to Bitstream overrall

v0.2.5

  • Fixed a major issue with per-player batching not acknowledging the stacks (due to it using array length checks still, as they now use dictionary)
  • Made per-player requests from the server take priority over all player requests on the server

I also just redid and debloated most of the main post, gets more straight to the point and is more organized + debloated now.

v1.0.0

SwitchNet release version!

  • Added :Wait() and :WaitUnreliable() methods to both Server and Client objects
  • :Connect() and :Disconnect() on both Server and Client now have seperated functions for UnreliableRemoteEvent calls: :ConnectUnreliable() and :DisconnectUnreliable()
  • Further reworked batch + input handlers on both server and client
  • Cleaned up constructor logic on both server and client
  • Cleaned up some extra code everywhere else