Buffer module ( optimizing module )

I recently got interested in optimizing everything I can to make the game run as fast as possible and as smooth as possible. That led me down a rabbit hole to learn about buffering and optimizing remote event sending.

With that information i present to you my new buffer module!!!

This buffer is used for sending information through remote events from client to server or vice versa!

It’s used to compress numbers and strings down so when you send them over with remote events they don’t put that much load onto the server or respectively the client!

Here’s how to use it:

First you require the module.
image

After that you buffer the value you want ( in this case the number 20 ) and you send it over to the server.

image

On the side you want to receive it you require the module once again and listen for the event.

After that you just use the ReadBuffer function ( Remember: It has to have the same signed or unsigned property and you have to use the same function type that you used for writing to read the buffer. So if you used write8 you have to use read8. )

image
image

For strings, it works the exact same way, just use a different parameter when reading!



image

With all that said here is the module and i hope you guys can put it to good use!
BufferModule.lua (3.4 KB)

For anyone that is nerdy enough and wants to know all the logic on why and how this works you can either look at the buffer doc or just read the explanation below!

LUA ( or in this case, LUAU ) uses a universal type for numbers that takes up 8 bytes of memory which is an insanely high number and it also includes floating points which in general takes a lot of memory. With that said if you only need to send a small number or a number for type checking its way more efficient to compress that number down into a 1 byte instance making it up to 8 times more efficient!

Also, for anyone wondering:
8 bits (1 byte)

  • Signed: −2^7 → 2^7 − 1 (−128 → 127)
  • Unsigned: 0 → 2^8 − 1 (0 → 255)

16 bits (2 bytes)

  • Signed: −2^15 → 2^15 − 1 (−32,768 → 32,767)
  • Unsigned: 0 → 2^16 − 1 (0 → 65,535)

32 bits (4 bytes)

  • Signed: −2^31 → 2^31 − 1 (−2.1 billion → 2.1 billion)
  • Unsigned: 0 → 2^32 − 1 (0 → 4.29 billion)

64 bits (8 bytes)

  • Signed: −2^63 → 2^63 − 1 (−9.22 quintillion → 9.22 quintillion)
  • Unsigned: 0 → 2^64 − 1 (0 → 18.4 quintillion)

Thank you for anyone that has read this far. This is my first ever post so i hope i did good.

With all due respect,
Zixp ( SoulRhythm )
Have an amazing day and God bless!

5 Likes

Gonna try this in my game and see how it goes👍

1 Like

what is the point of this..? It’s just… buffer library wrapper that is even worse than the imperative way (which’ll even take less time to write).

1 Like

To make sending things over with remote events more performant. Im sorry to hear that my creation wasn’t of use for you. Can you elaborate on why and how it is worse than the imperative way? Also it will take less time to write but this is made for ease of use for people who aren’t that good with using buffers.

Thanks for the feedback
Have an amazing day and God bless!

1 Like

Not everything has to be optimized to the fullest extent, this is just a preference module. And wrapper modules tend to be more useful for beginners in certain areas.

1 Like


There’s already implemented buffer.writestring function and your string writing does O(n) amount of function calls instead of calling one C++ function that does all the things.
Also you’re calling type() function twice, which leads to less efficient runtime.

All the read functions do the same as I said before. So, in fact, for strings it’s heavily inefficient, and for numbers it’s just additional function call with an if statement.

In serious projects programmers have understanding of what they’ll send and what arguments each remote event will get. This gives them opportunity to delete type() calls and use only needed functions.

As an example, a PVZ TD placement system. You want to simulate the visual on client (to not make a huge load on server replication). With your module, I’d have to do Buffer16 and Buffer8 calls (because your module doesn’t support desired 24 bits size) and then unite all of them in to one buffer. If we talk about making Buffer32 and use bit32.replace, then we have 1 empty byte.

Instead, as I know that my unit placement is guaranteed to be 24 bits (3 bytes), I’ll just use bit32.replace and create buffer of 3 bytes size and then write in that buffer the number that was made after bit32.replace manipulations. (2^4=16, column amount = 10, 2^3=8, row amount=5, 6 = tilesize)


And since I know that POS.x, POS.z, ids[name] is guaranteed to return number, I don’t have to do type check. And with the said understandings, I can use just one function for read and write.

With your module, I’d have to create buffer16 and buffer8 and unite them | 1 buffer32 and have 1 byte wasted. Sending just 2 buffers will lead into more than 1 read function call, overall decreasing the perfomance.

buffer wasn’t made for people who don’t understand compression. However, if we talk about roblox programmer as a person who got inspired by YT guides and thinks programming is easy, then this is fair.

Beginners commonly don’t use buffer. And the OP tends to talk about speed (“game run as fast as possible”). I have rights to talk about further optimization, since it’s literally the topic here.

1 Like

Also, in my initial reply I forgot to mention that lua and luau strings already include each character size, so for strings in Buffer16 and Buffer32 you’re making a ton of unused memory.

I appreciate the feedback. This is a lot of interest information and i am glad you shared. I’ll make sure to look into it and try improve this as much as i can!

Have a good day and God bless!

1 Like