Skip to content

Binary sbn #1486

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 5 commits into
base: main
Choose a base branch
from
Draft

Binary sbn #1486

wants to merge 5 commits into from

Conversation

QubaB
Copy link
Contributor

@QubaB QubaB commented Jul 2, 2025

This commit implements writing note as binary file. It does not convert note to Json and save Json so especially reading of note is much faster.

When reading note file Json is also not used so reconstruction is faster.

(Json is internally only used to save/read quill, i.e. editor).

There is not solved versioning of note file. It means when new version of note will be read by older version of Saber, it will fail to read.

The purpose of this commit is provide alternative way to save/read note and improve speed of reading.

Int the preferences is check box "Save as binary" so this feature can be switched on only for testing.

Floating values of stroke points are stored as 4 byte integers (float multiplied by 1000, and rounded). It saves note size and provides sufficient precision of 0.001 pt.

@QubaB
Copy link
Contributor Author

QubaB commented Jul 3, 2025

In the pull request is missing storing StrokeOptions. I did not noticed that it is another package and accidentally clened it. I must create code again.

@QubaB
Copy link
Contributor Author

QubaB commented Jul 3, 2025

now commit is completed and can be tested

On my Samsung Tab S6 is note which was read 10 seconds now read in much less than second.

@Iey4iej3
Copy link

Iey4iej3 commented Jul 4, 2025

Have you compared file sizes?

@QubaB
Copy link
Contributor Author

QubaB commented Jul 6, 2025

Normal file is 32 MB, binary file 16 MB. File contains only strokes. I used 4 bytes format of number instead of 8 bytes to store position.

@Iey4iej3
Copy link

Iey4iej3 commented Jul 6, 2025

I am a bit confused. If I understand correctly, the current files are saved using bson, and your pull request saves them as raw binaries instead? It should be more or less of the same size as current files (or slightly smaller, by eliminating the overheads of bson), if you save them with the same precision?

@QubaB
Copy link
Contributor Author

QubaB commented Jul 6, 2025

I do not save double (8 bytes) but scaled integers (4 bytes) to save memory. 4 byte integer can have value +-2147483648. I take double multiply it by 1000 and save this number rounded to integer. I suppose that precision of 0.001 point is sufficient. Still I can handle canvas about 2147483 points (saber use 1000x1400 by default) so much more than needed (precision can be improved by multiplying 10000 or 100000 with sufficient size of canvas 21474 points and precision 0.00001). I do not use floats because if I have canvas of size 10000 points I have resolution of only 0.01 point. I used this approach to have smaller file size because each stroke point is 2 doubles (or 3 in case of pen pressure). This simplification save half of file size.

The main reason of fast reading is that original code uses bson -> json -> data structures and it is slow (transfer to json). My method use binary file -> data structures.

Using Json is nice when You want to be able to read newer file versions (more features) in old Saber. It interprets only known features.
In my approach I did not take care about different versions of file. It is a draft. I hope that someone skilled can improve it. My goal was to see if it is possible to load note faster than in the current implementation and it is at least 10 times faster.

@Iey4iej3
Copy link

Iey4iej3 commented Jul 6, 2025

I have no idea about current infrastructures, but at least decades ago, the performance for integral arithmetic is much better than float arithmetic.

The main reason of fast reading is that original code uses bson -> json -> data structures and it is slow (transfer to json). My method use binary file -> data structures.

Is json ASCII texts, e.g. the ASCII string "1234" for the integer 1234? Then it is ridiculously inefficient. Is it possible to read data structures directly from bson?

@QubaB
Copy link
Contributor Author

QubaB commented Jul 7, 2025

I use integers only for storage. during reading they are recalculated to doubles because Flutter uses doubles to draw objects.

Json is combination of ASCII and doubles. It in fact list of different values. But it is converted to/from bson using strings. It is elegant to work with it, but it is slow.

All data structures are objects. They must be read/stored using its methods storing/reading only important data (positions of stroke points, line type, color, ...).

@Iey4iej3
Copy link

Iey4iej3 commented Jul 7, 2025

Json is combination of ASCII and doubles. It in fact list of different values. But it is converted to/from bson using strings. It is elegant to work with it, but it is slow.

Do you mean that, if one wants to convert some data structure to bson, it has to be firstly converted to strings? According to https://www.mongodb.com/resources/languages/bson, bson natively supports int32 and double, say, and it looks like that the code in https://www.reddit.com/r/golang/comments/wfh6k2/working_with_bson_and_struct_literal_meaning/ does not convert the data structure into an intermediary json?

I mean, it looks like that you could keep the current bson storage, and just write a more efficient converter which does not go through the extra layer of json? This seems to keep maximal compatibility.

@Iey4iej3
Copy link

Iey4iej3 commented Jul 7, 2025

In addition, it looks like that, even for the original bson storage, we could replace double by int, which would lead to a reduction of storage. A new issue post: #1488

@QubaB
Copy link
Contributor Author

QubaB commented Jul 7, 2025

Json is combination of ASCII and doubles. It in fact list of different values. But it is converted to/from bson using strings. It is elegant to work with it, but it is slow.

Do you mean that, if one wants to convert some data structure to bson, it has to be firstly converted to strings? According to https://www.mongodb.com/resources/languages/bson, bson natively supports int32 and double, say, and it looks like that the code in https://www.reddit.com/r/golang/comments/wfh6k2/working_with_bson_and_struct_literal_meaning/ does not convert the data structure into an intermediary json?

I mean, it looks like that you could keep the current bson storage, and just write a more efficient converter which does not go through the extra layer of json? This seems to keep maximal compatibility.

I did not studied original code too much, so did not care about bson (I used it to store only "text editor" - quill - stuff to String and then write it to file). I simply wanted to store data directly to file without any intermediate structures and see if it is faster. May be I do not see further consequencies and my code is wrong, but we at least know, that reading notes can be faster.

I think that using Json as intermediate causes slow reading of notes and it should be managed differently. It is on @adil192 to decide how to implement it (if at all). If it will not be implemented, I will use my draft for my personal use.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants