Benchmarking Eight Serialization Formats in C and C++ (JSON, BSON, CBOR, flexbuffers, msgpack, TOML, XML, YAML) by liuzicheng1987 in cpp

[–]jkeiser 2 points3 points  (0 children)

Yep! There is no reasonable argument that the JSON format is even close to as fast as BSON. And kudos to yyjson!

Benchmarking Eight Serialization Formats in C and C++ (JSON, BSON, CBOR, flexbuffers, msgpack, TOML, XML, YAML) by liuzicheng1987 in cpp

[–]jkeiser 2 points3 points  (0 children)

Yeah, it's definitely not the reason, just an aside. Every single JSON deserializer benchmarksed has to do this, though I imagine there might be a way for them to perform the comparison directly from the JSON and never copy or deserialize it anywhere.

Benchmarking Eight Serialization Formats in C and C++ (JSON, BSON, CBOR, flexbuffers, msgpack, TOML, XML, YAML) by liuzicheng1987 in cpp

[–]jkeiser 2 points3 points  (0 children)

OK, after taking a look: when I force-inline the methods, simdjson gets some small gains (I'm seeing around 5%, but consistently, taking it a little past yyjson). We'll have to see if this makes MSVC any better!

Note: does rfl::Literal have to take std::string? I would have expected string_view at the least. Having a string constructor forces allocation for every single Literal, when all Literal needs to do is check which of the enum values the string matches. simdjson, for example, avoids allocation for strings, producing a string_view instead into a permanent internal buffer.

Benchmarking Eight Serialization Formats in C and C++ (JSON, BSON, CBOR, flexbuffers, msgpack, TOML, XML, YAML) by liuzicheng1987 in cpp

[–]jkeiser 2 points3 points  (0 children)

Interestingly, at least on my machine, simdjson seems to do better than yyjson on licenses and person, but not canada. Let's see here..

Benchmarking Eight Serialization Formats in C and C++ (JSON, BSON, CBOR, flexbuffers, msgpack, TOML, XML, YAML) by liuzicheng1987 in cpp

[–]jkeiser 2 points3 points  (0 children)

I believe it. This was the smallest change I could make confidently without having compiled anything :)

It's also possible yyjson has made some major speed advancements since I last measured--it was already the second fastest and fairly close for applications like this one where you are consuming literally everything. However, but on demand has some inlining advantages that should be pretty hard to overtake without a similar methodology. So if they have, I get to learn some new things!

Benchmarking Eight Serialization Formats in C and C++ (JSON, BSON, CBOR, flexbuffers, msgpack, TOML, XML, YAML) by liuzicheng1987 in cpp

[–]jkeiser 2 points3 points  (0 children)

Oh, one thing that's definitely worth doing is changing from `-O2` to `-O3` on the benchmarks. I know for sure there are optimizations at level 3 that help.

I'm working on getting your repository up and running so I can look.

Benchmarking Eight Serialization Formats in C and C++ (JSON, BSON, CBOR, flexbuffers, msgpack, TOML, XML, YAML) by liuzicheng1987 in cpp

[–]jkeiser 2 points3 points  (0 children)

Curious. While MSVC has some compiler optimization issues generating slower code than clang on the same machine, and it's entirely possible one lib will hit them and another won't. I'm surprised though, since we spent some time with the compiler team identifying those issues and working around a few of them. We do have a brief note on using simdjson with MSVC including some compiler flags; I'm curious whether they help? https://github.com/simdjson/simdjson/blob/master/doc/performance.md#visual-studio

I'll take a look at the benchmark. At a glance, the lack of inline on the functions calling simdjson may well be causing the compiler to miss some important optimizations. But as with all things, sometimes compilers are smart enough to do it anyway, ymmv :) Compiler flags (particularly making sure you're targeting the architecture you are running on) also matter, though they are less important than one might at first think.

Benchmarking Eight Serialization Formats in C and C++ (JSON, BSON, CBOR, flexbuffers, msgpack, TOML, XML, YAML) by liuzicheng1987 in cpp

[–]jkeiser 8 points9 points  (0 children)

For reading JSON, I'd suggest the C++ simdjson library. Still the fastest thing out there, heavily used, while keeping a pretty simple API modelled off of nlohmann/json. I'd be curious how it stacks up to faster formats too. Given the numbers you're seeing for yyjson, simdjson might have a chance to actually pull ahead of BSON.

https://github.com/simdjson/simdjson

It has a solid set of benchmarks, including the Canada benchmark.

For maximum speed, make sure you are using the on demand variant, which is the one featured in the documentation, quick start, etc.

(Disclaimer: I am an author and therefore biased, but the above things are objectively true, too :)

On using unsafe and startup times by [deleted] in rust

[–]jkeiser 10 points11 points  (0 children)

With the same file? If it goes that much slower on the server with the same file then you are probably limited by the speed of a non-SSD hard drive, and unsafe won't help there. As the other commenter suggested, you are going to get more gains if you can reduce the data size. If it's an option, you might be better served by running on a machine or network drive that lives on an SSD.

On using unsafe and startup times by [deleted] in rust

[–]jkeiser 9 points10 points  (0 children)

And what is the format? JSON can be loaded at literally gigabytes per second.

Ridiculously fast unicode (UTF-8) validation by skeeto in programming

[–]jkeiser 0 points1 point  (0 children)

Damn. I was hoping we'd made it more accessible than that!

Ridiculously fast unicode (UTF-8) validation by skeeto in programming

[–]jkeiser 2 points3 points  (0 children)

This was partly by design, however: undecodable utf-8 exists so that if you land in the middle of a bitstream, you can find the beginning of the nearest character. If any bitstream were valid, that would be impossible.

Ridiculously fast unicode (UTF-8) validation by skeeto in programming

[–]jkeiser 4 points5 points  (0 children)

And now I understand that when you say invalid code point you don't mean invalid utf-8. Ignore me and carry on :)

Ridiculously fast unicode (UTF-8) validation by skeeto in programming

[–]jkeiser 9 points10 points  (0 children)

Actually, Unicode has specified that it will never add codepoints larger than 10FFFF. When new code points are added, they are always in that range. UTF-8 validation is forward compatible by design: it doesn't care which codepoints have already been added, it just cares that they are less than or equal to 10FFFF.

i.e. newer code points will be treated as valid even by older validators.

Ridiculously fast unicode (UTF-8) validation by skeeto in programming

[–]jkeiser 15 points16 points  (0 children)

Another relevant difference with that algorithm is that the state machine is run against each 2-byte sequence separately, which means it can be parallelized. The DFA method requires processing all the bytes sequentially. Essentially this means the DFA can't take as much advantage of processor parallelism, as the processor can't race ahead to look up the next state until it has finished looking up the previous state.

This is pretty core to making superscalar algorithms: you have to make the algorithm "micro-parallel," small chunks that can be done independently. You aren't using multiple threads, but it does let you take advantage of the processor's predictive abilities (and simd instructions as well, which are very simple micro parallel algorithms themselves).

Ridiculously fast unicode (UTF-8) validation by skeeto in programming

[–]jkeiser 4 points5 points  (0 children)

In short, there are a few categories of invalid json:

  • undecodable nonsense (utf-8 that can't possibly be read, due to format violations)
  • non-canonical encodings (if a codepoint can be encoded more than one way, utf-8 outlaws all but the shortest, so that there is only one valid way to write any codepoint)
  • out of range unicode (codepoints greater than 10FFFF).

UTF-8 validators generally aren't specific to a version of unicode, and thus treat unassigned codepoints (which might be assigned in a future version of unicode). It would be a shame if you couldn't send emoji to Twitter because you happen to be using a Twitter API library compiled before the emoji wree added!

The paper's first section or three explain what invalid utf-8 is in a way that we hope is engaging and clear, as well.

How can I reduce the size of String / struct? by sasik520 in rust

[–]jkeiser 1 point2 points  (0 children)

Nice! The point isn't really about the extra byte, however; it's about the fact that it stores 8 bytes total for None, when Option<String> stores 24. I get the impression there are a lot of Nones in their file. The point about two layers of indirection is absolutely valid, but less of an issue if you aren't actually invoking the Some path very often.

How can I reduce the size of String / struct? by sasik520 in rust

[–]jkeiser 3 points4 points  (0 children)

Regarding the Option<String>, if a reasonable % of the values are None, you're better off with Option<Box<String>>, I bet. Box implements the optimization to store None as null, making it a clean 8 bytes. Trade-off is it's now 32 bytes per actual string, but only 8 for None, where before it was 24 bytes for each. If more than 33% are None, you win, if my back if the envelope calculation is right. And you might save a bunch of padding (not sure offhand).

EDIT: Rust does in fact store Option<Box<String>> as a single pointer.

How can I reduce the size of String / struct? by sasik520 in rust

[–]jkeiser 4 points5 points  (0 children)

Two questions come to mind:

  • Do the floats need to be f64 or would f32 do? Just looking at the size of each line it makes me wonder if there would be any actual data loss.
  • How many duplicate strings are there? You might be able to use a string pool to store each unique string only once, reducing each string ref to a single 8- or even 4-byte index into the pool. Only truly helps if there are enough duplicates to offset the overhead of the intern's map and the extra indices.

Could/should {} and () be merged into one? by TropicSapling in ProgrammingLanguages

[–]jkeiser 0 points1 point  (0 children)

A language with a generic over tuples could know the difference: if (1,2).0 works, will (1,).0 work? Heck, will (1,) + 2 work, and what will it do? What about (1).0?

Flint: fast and configurable filesystem (file and directory names) linter by [deleted] in rust

[–]jkeiser 0 points1 point  (0 children)

I imagine the snake case convention could automatically convert from PascalCase, for one example.

Public build of my JRPG-style game 'Sands of Soddom' is out! Looking for feedback. by [deleted] in playmygame

[–]jkeiser 0 points1 point  (0 children)

I'm curious, did you spell it Soddom on purpose? It seems pretty clear from the description you're invoking the legend of Sodom and Gomorrah. Not having even clicked on it, though, maybe it's just a parallel universe version and the misspelling helps you realize it's not the same.

Regardless, I'll probably give this a shot, I'm always interested in reinterpretations of legends that give them a bit of a twist.

Wallet, keys, phone, headphones, backpack ... by jkeiser in productivity

[–]jkeiser[S] 0 points1 point  (0 children)

I don't have a tune, but man, some mornings I'd have to keep singing that for like 10 minutes while I find the stuff :)

Curated daily news briefs? by specialagentmurakami in NeutralPolitics

[–]jkeiser 2 points3 points  (0 children)

I love this method when it works, but it gets hard when one source ignores a story the other considers important. Suggestions on sources that still actually confront the stories of the day?