Skip to content

Commit 2d48113

Browse files
committed
ncdb: derive coveritem flags from type defaults
The UCIS LRM defines IS_32BIT, HAS_GOAL, HAS_WEIGHT as structural flags determined by cover type, not per-bin state. All CVGBIN items have IS_32BIT|HAS_GOAL|HAS_WEIGHT (0x19); all others have IS_32BIT (0x01). These are now stored in COVER_TYPE_DEFAULTS and applied automatically during deserialization. coveritem_flags.bin only stores flags that DIFFER from the type default (exclusion flags, IS_BR_ELSE, IS_FSM_RESET, etc.). For typical databases this means 0 entries → member not written. Impact on merged.vdb benchmark (131K bins): - coveritem_flags.bin: 264KB → 0 (not written) - Read: 3.13s → 2.79s (-11%, ~340ms saved) - Write: 2.71s → 2.63s (-3%, ~80ms saved) - Merge: unchanged (fast path never touches flags) Full test suite: 1002 passed, 0 failed
1 parent ae8b3ff commit 2d48113

3 files changed

Lines changed: 27 additions & 18 deletions

File tree

src/ucis/ncdb/constants.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,21 +67,21 @@
6767
# Used by reader to reconstruct coveritem objects without per-item storage.
6868

6969
COVER_TYPE_DEFAULTS: dict = {
70-
CoverTypeT.TOGGLEBIN: (0, 0, 1),
71-
CoverTypeT.STMTBIN: (0, 0, 1),
72-
CoverTypeT.BRANCHBIN: (0, 0, 1),
73-
CoverTypeT.CONDBIN: (0, 0, 1),
74-
CoverTypeT.EXPRBIN: (0, 0, 1),
75-
CoverTypeT.FSMBIN: (0, 0, 1),
76-
CoverTypeT.CVGBIN: (0, 1, 1),
77-
CoverTypeT.DEFAULTBIN: (0, 0, 1),
78-
CoverTypeT.IGNOREBIN: (0, 0, 1),
79-
CoverTypeT.ILLEGALBIN: (0, 0, 1),
80-
CoverTypeT.BLOCKBIN: (0, 0, 1),
81-
CoverTypeT.COVERBIN: (0, 0, 1),
82-
CoverTypeT.ASSERTBIN: (0, 0, 1),
83-
CoverTypeT.PASSBIN: (0, 0, 1),
84-
CoverTypeT.FAILBIN: (0, 0, 1),
70+
CoverTypeT.TOGGLEBIN: (0x01, 0, 1),
71+
CoverTypeT.STMTBIN: (0x01, 0, 1),
72+
CoverTypeT.BRANCHBIN: (0x01, 0, 1),
73+
CoverTypeT.CONDBIN: (0x01, 0, 1),
74+
CoverTypeT.EXPRBIN: (0x01, 0, 1),
75+
CoverTypeT.FSMBIN: (0x01, 0, 1),
76+
CoverTypeT.CVGBIN: (0x19, 1, 1),
77+
CoverTypeT.DEFAULTBIN: (0x01, 0, 1),
78+
CoverTypeT.IGNOREBIN: (0x01, 0, 1),
79+
CoverTypeT.ILLEGALBIN: (0x01, 0, 1),
80+
CoverTypeT.BLOCKBIN: (0x01, 0, 1),
81+
CoverTypeT.COVERBIN: (0x01, 0, 1),
82+
CoverTypeT.ASSERTBIN: (0x01, 0, 1),
83+
CoverTypeT.PASSBIN: (0x01, 0, 1),
84+
CoverTypeT.FAILBIN: (0x01, 0, 1),
8585
}
8686

8787
# ── Scope-type → implicit child cover type mapping ────────────────────────

src/ucis/ncdb/coveritem_flags.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
from .varint import encode_varint, decode_varint
1919
from .dfs_util import dfs_scope_list
20+
from .constants import COVER_TYPE_DEFAULTS
2021

2122
_VERSION = 1
2223
_COVER_ALL = 0xFFFFFFFF
@@ -32,7 +33,9 @@ def serialize(self, db) -> bytes:
3233
for scope in scopes:
3334
for ci in scope.coverItems(_COVER_ALL):
3435
flags = ci.getCoverFlags()
35-
if flags != 0:
36+
ct = ci.getCoverData().type
37+
default_flags = COVER_TYPE_DEFAULTS.get(ct, (0, 0, 1))[0]
38+
if flags != default_flags:
3639
entries.append((global_ci_idx, flags))
3740
global_ci_idx += 1
3841

@@ -83,4 +86,8 @@ def deserialize(self, data: bytes, db) -> None:
8386
if entry_pos < len(entries) and entries[entry_pos][0] == global_ci_idx:
8487
ci.setCoverFlags(entries[entry_pos][1])
8588
entry_pos += 1
89+
else:
90+
ct = ci.getCoverData().type
91+
default_flags = COVER_TYPE_DEFAULTS.get(ct, (0, 0, 1))[0]
92+
ci.setCoverFlags(default_flags)
8693
global_ci_idx += 1

src/ucis/ncdb/scope_tree.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,8 @@ def _read_toggle_pair(self, data: bytes, offset: int, parent, counts_iter):
265265
# Create the two implicit TOGGLEBIN coveritems
266266
for (bin_name, count) in ((TOGGLE_BIN_0_TO_1, count_0to1),
267267
(TOGGLE_BIN_1_TO_0, count_1to0)):
268-
cd = CoverData(CoverTypeT.TOGGLEBIN, 0)
268+
cd = CoverData(CoverTypeT.TOGGLEBIN,
269+
COVER_TYPE_DEFAULTS.get(CoverTypeT.TOGGLEBIN, (0,0,1))[0])
269270
cd.data = count
270271
scope.createNextCover(bin_name, cd, None)
271272

@@ -344,7 +345,8 @@ def _read_regular_scope(self, data: bytes, offset: int, parent, counts_iter):
344345
ci_name_ref, offset = decode_varint(data, offset)
345346
ci_name = self._st.get(ci_name_ref)
346347
count = next(counts_iter, 0)
347-
cd = CoverData(child_cover_type, 0)
348+
default_flags = COVER_TYPE_DEFAULTS.get(child_cover_type, (0, 0, 1))[0]
349+
cd = CoverData(child_cover_type, default_flags)
348350
cd.data = count
349351
if at_least_override is not None or (child_cover_type and
350352
COVER_TYPE_DEFAULTS.get(child_cover_type, (0,0,1))[1] != 0):

0 commit comments

Comments
 (0)