jepsen-io/maelstrom

"Map" with random key ordering would lead to excessive failure in Datomic chapter

Closed this issue · 5 comments

Specifically for this https://github.com/jepsen-io/maelstrom/blob/main/doc/05-datomic/02-shared-state.md#database-as-value and I'm mostly just wondering if this should be mentioned in the tutorial. (you might also encounter this issue when doing training :D)

I'm using Rust and since the builtin HashMap type could reorder keys when growing, it could cause lots of failure when used blindly in CAS.

For example I'd have more than half failed transactions even for very few operations:

 :stats {:valid? true,
         :count 22,
         :ok-count 7,
         :fail-count 15,

For longer runs it's even worse so I didn't bother to finish any. Looking at the message diagram points me to believe this is due to ordering (of HashMap keys):

image

Luckily there's also a built-in type which is sorted by its keys and it solved the issue for me, so I would get results like this: (same with yet another type)

 :stats {:valid? true,
         :count 2045,
         :ok-count 1924,
         :fail-count 121,

Which is more in-line with the results in the tutorial.

aphyr commented

Er, it looks like you're serializing your map to a string instead of writing it directly as JSON. The tutorial doesn't do that, does it?

I mean it ultimately still needs to be serialized (to string)? E.g. it's done here https://github.com/jepsen-io/maelstrom/blob/main/demo/ruby/node.rb#L74 in example code, I think this will cause issue as long as the serialization can reorder keys.

I'm mostly thinking that the high fail rate could be overlooked, since it doesn't "break" CAS semantic, just not ideal behaviour.

aphyr commented

You're serializing a JSON string inside a JSON string. You can do that, sure! But if you do, yes, of course, you'll be responsible for the ordering semantics. :-)

Ah, I see what you mean now xD, let me check if this will be fixed if I tweak it to not use strings.

It definitely works by switching to use JSON maps :)

 :stats {:valid? true,
         :count 2020,
         :ok-count 1832,
         :fail-count 188,

Sorry for the OP!