-
Notifications
You must be signed in to change notification settings - Fork 133
Description
I know that on numerous occasions we've had discussions within the working group on whether the Tree vs. Directory dichotomy is truly necessary, and whether there are ways to eliminate it. Let me make it clear up front that this issue is filed under the assumption that we do want to keep these separate like we have today, which is why I'm not posting this under #159 or #170. It's just low hanging fruit.
The last couple of days I've worked on optimising handling of large Tree objects in bb-clientd. Whereas some of the other Protobuf messages can sometimes become hundreds of kilobytes in size (e.g., Command), it's not impossible for Trees to become dozens of megabytes. While working on optimising this area, I realised that my life would have been a lot easier if Trees were stored as a varint delimited stream of Directory messages (just like Bazel --build_event_binary_file). My suggestion would be to make it topologically sorted (parents before children), so that the root of the Tree comes first. Some advantages:
- Because of the topological sorting, you can instantiate the contents of a Tree on a native file system in a streaming manner. Memory consumption of such an extraction tool would only be proportional to the number of referenced child directories that have not yet been observed.
- Similarly, you can do one-shot path lookups (for paths without "..") by doing a forward scan against the stream, only unmarshaling directory objects that match the length and hash yielded by the parent.
- Right now you see that consumers of Tree first unmarshal the message, and then marshal each of the child directories again, just so that their hash can be computed. This implicitly assumes that the producer and consumer use the same strategy for marshaling. By using a varint delimited stream, consumers have direct access to directories in marshaled form, meaning that both this assumption and the redundant marshaling are eliminated.
- In bb-clientd I need to be able to have fast random access to Tree objects. To facilitate this, I'm basically storing the Tree object in the client-side CAS just once, but creating n+1 entries in the index. One for the Tree as a whole, and one for each of the child directories, pointing to byte ranges in the Tree's bytestream that correspond to the individual directory messages. That way these directory messages become directly addressable. This happens to be possible today, only because Protobuf messages are encoded identically regardless of the depth at which they are placed. The format I'm proposing not only allows me to eliminate this assumption, it means I can also compute the n additional entries in a streaming manner.