HackerTrans
TopNewTrendsCommentsPastAskShowJobs

eliasdejong

no profile record

Submissions

Show HN: Lite³ – A JSON-Compatible Zero-Copy Serialization Format in 9.3 kB of C

github.com
4 points·by eliasdejong·8 tháng trước·0 comments

comments

eliasdejong
·tháng trước·discuss
standby, server is taking some load. should be back up soon
eliasdejong
·tháng trước·discuss
Creator here,

For those interested:

- ZERO CLIENT-SIDE OR INLINE JAVASCRIPT except Datastar & Datastar attributes

- real-time multiplayer powered by CQRS

- 45x45 characters chunks stored in LMDB

- all characters are read & written through FULL ACID TRANSACTIONS. no shortcuts. no relaxations

- chunk-based viewport culling

- LZ4 compression on chunk-basis to remove white space and repeating chars

- runs on a 5,52 euro/mo VPS in Germany, cheapest tier in public cloud

Stack: Datastar, Python/FastAPI, LMDB
eliasdejong
·tháng trước·discuss
check info tab on the top
eliasdejong
·2 tháng trước·discuss
Read your blogpost, I will need a code editor soon so I might have a stab at hacking something together.

> but this doesn’t really work in mobile and it messes with the selection

I haven't tested it personally, but on the OverType they claim "excellect mobile support".
eliasdejong
·2 tháng trước·discuss
CodeMirror is great, but still requires a lot of clientside JavaScript. I wonder if it would be possible to create a code editor in the same style OverType[0], where the editor is basically just an HTML textarea. You would need 70% less JavaScript code to do exactly the same thing, and it supports syntax highlighting out of the box[1].

[0]: https://github.com/panphora/overtype

[1]: https://github.com/panphora/overtype/pull/35
eliasdejong
·5 tháng trước·discuss
Checkout DataStar, it's also a hypermedia web framework but it subsumes the functionality of htmx, is faster, more efficient and fits inside 11 KiB. It uses SSE + brotli streaming compression to achieve compression ratios up to 4000x. It makes the web client completely stateless. Building a webapp cannoy be simpler really.
eliasdejong
·5 tháng trước·discuss
To me this sentiment is silly. Programming was never about the act of writing, but about making the computer do something. Now we can ask computers to helps us write instructions for them. Great if you ask me. And no, your job is not going away because human maintainers will always be required to review changes, communicate with stakeholders and provide a vision for the projects. I have yet to see a chatbot that can REDUCE entropy inside a codebases rather than continuously increase it with more and more slop.
eliasdejong
·5 tháng trước·discuss
Very cool project! Being able to replay history is huge and makes it possible to look back in time without having to make full copies of the database. This is something that is very much lacking in many SQL systems where you need 'temporal tables' to achieve the same effect, but those are really limited as they have to be setup specifically and often duplicate data unnecessarily. If you are interested in this topic, I suggest you study Datomic and the EAVT data model. This is likely where database architecture in the future will be headed.

> The database is stored in memory. So it must be small enough to fit in RAM, and the full journal has to be replayed from scratch when opening a file.

For larger datasets, you really want disk support. Using something like SQLite or DuckDB as an append-only store is another way to achieve this effect.

Also lack of a proper query language will be a problem for long term serious use. A simple hand-rolled program API can only get you so far, until you need more advanced querying.

> Unlike XML or JSON, joedb is a binary file format that does not require any parsing. So, joedb files are much smaller, and processing data is much faster.

Some time ago I created a JSON-compatible serialization format that is zero-copy (no parsing required): https://github.com/fastserial/lite3

It doesn't do transactions or history versioning, but it is also very fast in memory. Something like jq or JSONPath on a disk-file version of this format could be interesting.
eliasdejong
·6 tháng trước·discuss
Performance of Protobuf is a joke. Why not use a zero copy format so that serialization is free? For example, my format Lite³ which outperforms Google Flatbuffers by 242x: https://github.com/fastserial/lite3
eliasdejong
·6 tháng trước·discuss
See also, RUM Conjecture: https://www.codementor.io/@arpitbhayani/the-rum-conjecture-1...

Conceptually similar to CAP, but with storage trade-offs. The idea is you can only pick 2 out of 3.
eliasdejong
·6 tháng trước·discuss
Really excellent research and well written, congrats. Shows that io_uring really brings extra performance when properly used, and not simply as a drop-in replacement.

> With IOPOLL, completion events are polled directly from the NVMe device queue, either by the application or by the kernel SQPOLL thread (cf. Section 2), replacing interrupt-based signaling. This removes interrupt setup and handling overhead but disables non-polled I/O, such as sockets, within the same ring.

> Treating io_uring as a drop-in replacement in a traditional I/O-worker design is inadequate. Instead, io_uring requires a ring-per-thread design that overlaps computation and I/O within the same thread.

1) So does this mean that if you want to take advantage of IOPOLL, you should use two rings per thread: one for network and one for storage?

2) SQPoll is shown in the graph as outperforming IOPoll. I assume both polling options are mutually exclusive?

3) I'd be interested in what the considerations are (if any) for using IOPoll over SQPoll.

4) Additional question: I assume for a modern DBMS you would want to run this as thread-per core?
eliasdejong
·6 tháng trước·discuss
The library contains iterator functions that can be used to recursively traverse a message from the root and discover the entire structure. Then every value can be checked for defined constraints appropriately while at the same time validating the traversal paths. Also a schema description format is needed, perhaps something like JSONSchema can be used.

Doing this by definition requires processing an entire message which can be a little slow, so it is best done in C and exposed through CPython bindings / CFFI.
eliasdejong
·6 tháng trước·discuss
Imagine if you measured the speed of beer delivery by the rate at which beer cans can be packed/unpacked from truck pallets. But then somebody shows up with a tanker truck and starts pumping beer directly in and out. You might argue this is 'unfair' because the tanker is not doing any packing or unpacking. But then you realize it was never about packing speed in the first place. It was about delivering beer.
eliasdejong
·6 tháng trước·discuss
The primary motivations were performance requirements and frustration with schema formats.

The ability to mutate serialized data allows for 2 things:

1) Services exchanging messages and making small changes each time e.g. adding a timestamp without full reserialization overhead.

2) A message producer can keep a message 'template' ready and only change the necessary fields each time before sending. As a result, serializing becomes practically free from a performance perspective.
eliasdejong
·6 tháng trước·discuss
No, I have not benchmarked yet against other languages. Rkyv is Rust only.

One primary difference is that Rkyv does not support in-place mutation. So any modification of a message requires full reserialization, unlike Lite³.
eliasdejong
·6 tháng trước·discuss
> A key feature of this code is that it skips CPU cache when copying

Are those numbers also measured while skipping the CPU cache?
eliasdejong
·6 tháng trước·discuss
Yes, any zero-copy format in general will have this advantage because reading a value is essentially just a pointer dereference. Most of the message data can be completely ignored, so the CPU never needs to see it. Only the actual data accessed counts towards the limit.

Btw: in my project README I have benchmarks against Cap'N Proto & Google Flatbuffers.
eliasdejong
·6 tháng trước·discuss
If the new value is equal size or smaller, it will overwrite the old value in-place. If it is larger, then the new value is appended to the buffer and the index structure is updated to point to the new location.

In the case of append, the old value still lives inside the buffer but is zeroed out. This means that if you keep replacing variable-sized elements, over time the buffer will fragment. You can vacuum a message by recursively writing it from the root to a new buffer. This will clear out the unused space. This operation can be delayed for as long as you like.

If you are only setting fixed-size values like integers or floats, then the buffer never grows as they are always updated in-place.
eliasdejong
·6 tháng trước·discuss
The limit is the number of outstanding cache line requests to the memory controller. CPUs have a fixed number of slots for this, around 10-12 usually. Intel calls them LFBs (Line Fill Buffers) and AMD MSHRs (Miss Status Holding Registers). When the slots are filled, the CPU can issue no more requests and has to wait for them to complete. Apple M chips (probably) have more slots and the memory is physically packaged together with the CPU, so they get better numbers.
eliasdejong
·6 tháng trước·discuss
Being schemaless is deliberate design decision as it eliminates the need for managing and building schema files. By not requiring schema, messages are always readable to arbitrary consumers.

If you want schema, it must be done by the application through runtime type checking. All messages contain type information. Though I do see the value of adding pydantic-like schema checking in the future.

EDIT: Regarding message size, Lite³ does demand a message size penalty for being schemaless and fully indexed at the same time. Though if you are using it in an RPC / streaming setting, this can be negated through brotli/zstd/dict compression.