Skip to content
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

SSZ cleanup #1073

Closed
wants to merge 4 commits into from
Closed

SSZ cleanup #1073

wants to merge 4 commits into from

Conversation

arnetheduck
Copy link
Member

  • be stricter about SSZ length prefix
  • compute zeroHash list at compile time
  • remove SSZ schema stuff
  • move SSZ navigation to ncli
  • cleanup a few leftover openArray uses

* be stricter about SSZ length prefix
* compute zeroHash list at compile time
* remove SSZ schema stuff
* move SSZ navigation to ncli
* cleanup a few leftover openArray uses
@zah
Copy link
Contributor

zah commented May 28, 2020

compute zeroHash list at compile time

What is the compilation time increase stemming from this? Not slowing down compilation was the primary motivation for me for not doing it this way.

@@ -961,25 +961,3 @@ programMain:
config.depositContractAddress,
config.depositPrivateKey,
delayGenerator)

of query:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The query commands are currently used in the multinet repo to extract the genesis time (we used to rely on JSON in the past).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can they be updated to use ncli? the navigation brings in a bunch of memrange code that I'd rather avoid in the beacon_node proper

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, what I meant is that it would be nice to do a PR there as well that will land together with this one.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@onqtam can you help with this? you've been looking at the multinet scrips recently - it would involve building ncli_query.

generally I feel the feature would be better off if it supported something like graphql as query language

Copy link
Contributor

@onqtam onqtam May 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@arnetheduck actually 1+ month ago zahary told me that I could modernize the multinet scripts from parsing the json file to using this query subcommand but I never did it since what we had was already working (in terms of extracting the genesis time at least - my bad), so it should be fine to remove this. I could still migrate the scripts there to use ncli, but that would be unrelated to this PR - this change should be good to go.

@@ -63,6 +66,18 @@ serializationFormat SSZ,
Writer = SszWriter,
PreferedOutput = seq[byte]

template decode*(Format: type SSZ,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need these?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to pass the more conservative maxObjectSize without having to change all call sites

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ie the branch removes the arbitrary default - I haven't looked at it in detail, but the SSZ library should always know and use the length of the given buffer to constrain the instances it creates - this is a security feature to fail fast on any overlong length fields that would otherwise try to cause the library to allocate a large seq of stuff without backing it up with actual contents

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think maxObjectSize should be removed altogether. It was a temporary way of doing things that is no longer necessary with some improvements in the FastStreams API such as withReadableRange.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok - that's beyond my familiarity with the serialization stuff, sounds like something for a separate PR at which point removing these two overloads is trivial

result = T readSszValue(input, List[byte, maxExpectedSize])
const maxExpectedSize = (val.maxLen div 8) + 1
# TODO can't cast here..
var v: List[byte, maxExpectedSize]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the unnecessary copy produced here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

because there was a weird compiler error I was unable to fix in reasonable time, when trying to pass (List[byte,..)(val) , complaining that it's not a var any more

Copy link
Contributor

@zah zah May 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, let's not introduce performance regressions in cleanup PRs. After all, this is a list, one of the largest structures that appear in the consensus data types.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the alternative is a stack overflow because of the bug with arrays and RVO - I don't understand the compiler error tbh, maybe you have any good ideas? all that should be needed here is a cast

Copy link
Member Author

@arnetheduck arnetheduck May 28, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, it's a bitlist - ie typically a very small - we have no idea about the performance impact of all these bugs, but generally, this branch does not noticeably slow anything down (on the contrary, I would suspect it speeds things up because of the bugs it works around) - but all these things are idle speculation since we don't benchmark things, which would be the way to actually tell - like we've seen in the past, since 20 copies on the way from the network to ssz decode don't matter, neither will this seq copy - focus on the right things before bringing up performance

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hadn't noticed that this is the BitList branch indeed. It's less of a concern then, but I'll take a look at the compilation error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can cast[var List[byte,...]](val.addr) as a workaround. Known issue with distinct types or pointer(...) conversion

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I've reached the same conclusion here:
239224d

Found a Nim bug along the way :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm glad we're keeping the nim-bugs-per-PR ratio stable

@arnetheduck
Copy link
Member Author

compute zeroHash list at compile time

What is the compilation time increase stemming from this? Not slowing down compilation was the primary motivation for me for not doing it this way.

time ../env.sh nim c test_ssz

pre:

real	0m5,387s
user	0m5,105s
sys	0m0,259s

post:

real	0m5,270s
user	0m5,003s
sys	0m0,245s

@zah
Copy link
Contributor

zah commented May 28, 2020

I've made some local tests by increasing the size of the zeroHashes array in increments of 1000.
It seems that Nim can compute 1000 hashes in roughly 0.5s on my machine and this will put the cost of 100 hashes to around 0.05s. I guess that's reasonable, although there is nothing really gained from the change.

You can improve this further by computing the precise number of zeroHashes needed by introducing a maxLimit constant (currently set to VALIDATOR_REGISTRY_LIMIT = 1099511627776). You can see how treeHeight is computed in createMerkleizer.

@arnetheduck
Copy link
Member Author

arnetheduck commented May 28, 2020

You can improve this further by computing the precise number of zeroHashes needed by introducing a maxLimit constant (currently set to VALIDATOR_REGISTRY_LIMIT = 1099511627776). You can see how treeHeight is computed in createMerkleizer.

I put the limit at 64 which allows lists up to 2**64 which is far beyond what a computer can ever support - but at least I'll sleep well knowing that it's statically verifiable as long as we stay in int64-land.

given the overall compile time goes down with this branch, I'm pretty happy - full picture > OCD

@zah
Copy link
Contributor

zah commented May 28, 2020

Rebased here:
#1082

@zah zah closed this May 28, 2020
@tersec tersec mentioned this pull request Jun 18, 2020
67 tasks
@arnetheduck arnetheduck deleted the ssz-cleanup branch September 11, 2020 06:13
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.

4 participants