bkconrad / wasabi

MIT License
31 stars 1 forks source link

enhancement idea: send only deltas #25

Closed mreinstein closed 10 years ago

mreinstein commented 10 years ago

What would be a nice way to save even more bandwidth would be to specify a "send deltas" mode, where the serialization code tracks the last sent value, and only streams data if at least 1 field has changed.

bkconrad commented 10 years ago

I've been thinking about how to do this for a couple days, and I think the best (only?) way would be to keep some sort of cache of each replicated object's properties.

Now that Wasabi supports nested objects, this is somewhat complicated. The best way I can think of is to take a deep copy of each object on the server during each update where a field changes, and traverse it in tandem with the real object to find the deltas.

This cache can live completely inside the Connection object, so at least it won't be as intrusive as wsbSerialNumber and friends.

I think this ends up being between linear and O(n^2) time, depending on the frequency of attribute updates. Worst case is when no attributes are updated. All of that is fine since it's an option, but it's worth documenting.

An alternative idea I had was making a .wsbDirty attribute, mark it false after an update is sent, and let the user mark it true as needed. I'm starting to feel guilty about intrusively hanging data on user's objects, but something like this would reduce it to O(n) and save a ton of memory, while also introducing the possibility of user error.

Thoughts?

mreinstein commented 10 years ago

Here's the algorithm I'm thinking of. This would be done every time an object is being sent over the wire:

bytesToSend = pack object
crc = crc32 bytesToSend
if crc != lastCrc
   send bytesToSend
   lastCrc = crc

I don't know if crc32 is the right algorithm, maybe theres a better choice. but the idea is that you generate a signature for the bytes you're about to send, and only send an object update if anything has changed. Granted this is not as efficient as sending partial objects, but for objects that dont change at all over several frames this will still be a pretty nice bandwidth savings, fairly simple to implement, has low memory requirements, and it's O(1).

Thoughts?

mreinstein commented 10 years ago

bonus points if this feature can be turned on/off for a given connection or server. :)

bkconrad commented 10 years ago

I like the checksum idea, because it's cheap, unobtrusive, and #20 requires checksums of some sort, anyway. I'm going to try that first and see how it performs.

bkconrad commented 10 years ago

Thanks, @mreinstein!

This turned out to be a really good idea. It actually saves CPU as well as bandwidth if there are enough objects not getting their data changed, because it's so expensive to prepare Bitstream contents for transmission.

Still working out how to configure it, though

mreinstein commented 10 years ago

Very cool, can't wait to use it :+1:

Are you going to publish a new version to npm soon? It seems like a lot of features and non-breaking improvements have been added since the 0.2.0 release. Assuming api didn't have any breaking changes we could bump to 0.3.0 :)

bkconrad commented 10 years ago

I was just thinking about that, in fact.

I'm building a small game that's more complex than the wasabi_example to demonstrate the more advanced features (and stress test them). Once there's a bit of testing done "in the wild" I definitely want to publish as 0.3.0 :)