metauni / metaboard

Multiplayer drawing boards for sharing knowledge in Roblox.
Mozilla Public License 2.0
28 stars 6 forks source link

Curve length limit needed #77

Open blinkybool opened 1 year ago

blinkybool commented 1 year ago

The v3 persistence format has a constraint on curve length. If a serialised figure is > 3.5MB, that figure is ignored, so that we don't ever exceed the limit on a single "chunk" (datastore entry).

This would be a very very long curve, and drawing such a curve might also cause performance issues. There are parts of the code that treat figures as whole units. For example, when the client renders a board in the workspace for the first time, they render up to 100 lines, then 100 more lines, then 100 more lines etc. But this is done by continuing to render more whole-figures until the budget is exceeded, so at some point there's an unbounded jump that could render a length 2000 curve. In principle I could carry that budget through to render only part of the curve, but it would be better to tame the type of curves so that they are all within some given upper bound.

This would be a bad solution if the effect was that your pen suddenly stopped drawing after a given length is reached, so what should actually happen is that at a certain length, the curve you're drawing ends and a new one begins in the same spot.

There's two ways to do this:

  1. User input stage: Trigger "tool up" and "tool down" instantaneously after a certain number of lines are drawn
  2. Within the drawing task: A drawing task actually creates multiple curves, adding points to the latest curve until it hits the limit.

I think (2) is the clear winner, because in (1), you are making multiple drawing tasks, so hitting undo will only undo the very last section of the curve. In (1) you also need to inspect the type of the drawing task and inspect its curve contents to keep track of the length so far. This is just a sign that it's the drawing task's business.

The remaining question is what number to choose. Ideally it could be low enough that rendering any figure can be rendered within a single frame, but if it's too low, we'll end up inflating #figures, which we want to keep relatively low.

blinkybool commented 1 year ago

A simple test shows that rendering 300 lines at once (with parts) starts to make little bumps in the microprofiler, so I propose 256 (I have aspirations to try using 32bit numbers for the curve mask, instead of a dictionary).

How long is a curve with 256 lines? Here's a demo where they get cut short at 256.

https://user-images.githubusercontent.com/31099215/180986608-03ae4660-0f4a-47c7-a8ea-fdf9e2693b8c.MP4

This seems long enough that normal writing and simple diagrams will almost never even cause the multi-figure behaviour (hence won't inflate the figure count).

Any objections to this upper bound? Too small?