RakNet RemoteEvent ``:FireServer`` byte length analysis

Roblox uses RakNet. Which is networking. It seems to be part of how networking works on Roblox, at least one part of it, e.g. Replicator.

I assume it’s something about ClientReplicator and ServerReplicator. That there’s some sort of working instance referred to as the Replicator, that bridges replications of server things including :FireServer().

 

The Replicator has interesting references, such as Replicator::ItemSender::sendPacketV2(), that one can find out of FLog. There are also different types of packets for the Replicator, apparently.

Not sure if for RemoteEvents and RemoteFunctions it’s Type=7, but this information is probably very useless, if you’re just trying to see the data size.

 

The purpose of a RemoteEvent is an illusion. It’s just an Instance with Functions. In reality it’s just another part of the Replicator. I think the Replicator just bridges and connects everything together related to RemoteEvents.

 

There are some debugging Fast Flags, but I haven’t stumbled upon one that let’s me examine these sizes. The rest is… either named different, or we just can’t debug it… :(

Apparently, what RakNet does is to initiate a “bit stream”. I could be wrong though. It’s difficult to tell how data gets sent or how it arrives. But with WireShark, I am able to see a “Length”.

image


 

I have to define x where x is some other metadata, that I don’t really know what they could be. And to get the length, I just do math it with offset to get the length.

 

Command Length
:FireServer() x
:FireServer(nil) x + 1
:FireServer(true) x + 2
:FireServer({}) x + 2
:FireServer("") x + 2
:FireServer(nil, nil) x + 2
:FireServer("a") x + 3
:FireServer(buffer.create(0)) x + 3
:FireServer("ab") x + 4
:FireServer("abc") x + 5
:FireServer(1) x + 9
:FireServer(-1) x + 9
:FireServer(1_000_000) x + 9
:FireServer(-1_000_000) x + 9

You can save 1 Byte if you don’t use nil in an argumentless argument. I don’t think anybody does that but, it is a very intersting fact.


 

:FireServer(function() end))

Length: x + 1, Can’t send a pure function through a RemoveEvent, so it turns to nil


local buf = buffer.create(1)
buffer.writei8(buf, 0, 1)
game.ReplicatedStorage.RemoteEvent:FireServer(buf)

Length: x + 4

If you specified 0 as the buffer size, the length would be x + 3. If you specified 2 as the buffer size it would be x + 5

 


local tbl = {""}
game.ReplicatedStorage.RemoteEvent:FireServer(tbl)

-- or

local tbl = {
	[1] = ""
}

game.ReplicatedStorage.RemoteEvent:FireServer(tbl)

Length: x + 4. If we go to the table at the top we can see that a pure {} takes a length of 2 bytes and "" as well. Combined together we have 4 and the measurements didn’t lie either.

 


local tbl = {
	"",
	"",
}

game.ReplicatedStorage.RemoteEvent:FireServer(tbl)

Length: x + 6.

 


local tbl = {
	["abcd"] = "",
}

game.ReplicatedStorage.RemoteEvent:FireServer(tbl)

Length: x + 9.

 


game.ReplicatedStorage.RemoteEvent:FireServer(game.Workspace)

Length: x + 6. This length is maintained regardless whether it will end up as nil for the client. Whatever it is sending through is very unique.


local tbl = {
	[game.Workspace] = "",
}

game.ReplicatedStorage.RemoteEvent:FireServer(tbl)

This will probably differ, but the table key game.Workspace is turned into a string before it is even being sent through a RemoteEvent.

 

Conclusion

So numbers take 9 Bytes? :thinking:

At least, I think. That’s how it showed up in WireShark.

With buffer you can save a few amount of bytes. Whether it’s worth it, is a question you need to ask yourself.

You won’t be able to send through Instances using buffers however… Wondering about whether Roblox will offer some interesting features regarding that…

Array based tables seem alright.

If you have to send text through, you have to send text through. There isn’t much that you can change about that, I guess. You could also send through a “token”, as in those used for translations, or something.

 

Also buffer has some limit, but I didn’t examine what kind.

 

I like the difference between :FireServer() and :FireServer(nil). In the end, both will end up as nil for the Client.

As an attempt, I tried to see if there would be a major difference between, changing a IntValue's Value Property compared to :FireServer but, there wasn’t something that I noticed. These Replicators seem to replicate a similar size amount of data.

4 Likes

1 byte for the tag and 8 bytes for the number. That’s why everything including nil takes an extra byte.

Strings, tables and buffers also have another byte to signal the end (\0).

Instances are sent by an ID and are re-referenced by the receiver if a corresponding one exists.

3 Likes

This is really interesting. A lot of the relative performance impacts are intuitive, but it’s neat to be able to see what exactly is happening.

2 Likes