Reworked grm encoding a bit
This drops the leading count/mode byte, and instead uses mid=0 to
terminate grms. This shaves off 1 bytes from grmdeltas.
Previously, we needed the count/mode byte for a couple reasons:
- We needed to know the number of grm entries somehow, and there wasn't
always an obvious sentinel value. mid=-1, for example, is
unrepresentable with our unsigned leb128 encoding.
But now that development has settled, we can use mid=0.0 to figure out
the end-of-queue. mid=0.0 should always map to the root bookmark,
which doesn't make sense to delete, so it makes for a reasonable null
terminator here.
- It provided a route for future grm extensions, which could use the >2
count/mode encodings.
But I think we can use additional grm tag encodings for this.
There's only one gdelta tag so far, but the current plan for future
gdelta tags is to carve out the bottom 2 bits for redund like we do
with the struct tags:
LFSR_TAG_GDELTA 0x01tt v--- ---1 -ttt ttrr
LFSR_TAG_GRMDELTA 0x0100 v--- ---1 ---- ----
LFSR_TAG_GBMAPDELTA 0x0104 v--- ---1 ---- -1rr
LFSR_TAG_GDDTREEDELTA 0x0108 v--- ---1 ---- 1-rr
LFSR_TAG_GPTREEDELTA 0x010c v--- ---1 ---- 11rr
...
Decoding is a bit more complicated for gstate, since we will need to
xor those bits if mutable, but this avoids needing a full byte just
for redund in every auxiliary tree.
Long story short, we can leverage the lower 2 bits of the grm tag for
future extensions using the same mechanism.
This may seem like a lot of effort for only a handful of bytes, but keep
in mind each gdelta lives in more-or-less every mdir in the filesystem.
Also saves a bit of code/ctx:
code stack ctx
before: 35772 2368 640
after: 35768 (-0.0%) 2368 (+0.0%) 636 (-0.6%)
This commit is contained in:
+14
-18
@@ -2683,26 +2683,22 @@ class Gstate:
|
||||
|
||||
def __init__(self, mtree, tag, gdeltas):
|
||||
super().__init__(mtree, tag, gdeltas)
|
||||
queue = []
|
||||
d = 0
|
||||
count, d_ = fromleb128(self.data, d); d += d_
|
||||
rms = []
|
||||
if count <= 2:
|
||||
for _ in range(count):
|
||||
mid, d_ = fromleb128(self.data, d); d += d_
|
||||
mid = mtree.mid(mid)
|
||||
# map mbids -> -1 if mroot-inlined
|
||||
if mtree.mtree is None:
|
||||
mid = mtree.mid(-1, mid.mrid)
|
||||
rms.append(mid)
|
||||
self.count = count
|
||||
self.rms = rms
|
||||
for _ in range(2):
|
||||
mid, d_ = fromleb128(self.data, d); d += d_
|
||||
# a null mid (mid=0.0) terminates the grm queue
|
||||
if not mid:
|
||||
break
|
||||
mid = mtree.mid(mid)
|
||||
# map mbids -> -1 if mroot-inlined
|
||||
if mtree.mtree is None:
|
||||
mid = mtree.mid(-1, mid.mrid)
|
||||
queue.append(mid)
|
||||
self.queue = queue
|
||||
|
||||
def repr(self):
|
||||
return 'grm %s' % (
|
||||
'none' if self.count == 0
|
||||
else ' '.join(mid.repr() for mid in self.rms)
|
||||
if self.count <= 2
|
||||
else '0x%x %d' % (self.count, len(self.data)))
|
||||
return 'grm [%s]' % ', '.join(mid.repr() for mid in self.queue)
|
||||
|
||||
# keep track of known gstate
|
||||
_known = [g for g in Gstate.__subclasses__() if g.tag is not None]
|
||||
@@ -2918,7 +2914,7 @@ class Lfs:
|
||||
if not isinstance(mid, Mid):
|
||||
mid = self.mid(mid)
|
||||
|
||||
return mid in self.gstate.grm.rms
|
||||
return mid in self.gstate.grm.queue
|
||||
|
||||
# lookup operations
|
||||
def lookup(self, mid, mdir=None, *,
|
||||
|
||||
Reference in New Issue
Block a user