~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/btree_index.py

  • Committer: John Arbash Meinel
  • Date: 2010-08-03 20:56:39 UTC
  • mto: This revision was merged to the branch mainline in revision 5390.
  • Revision ID: john@arbash-meinel.com-20100803205639-k23colcozyd14440
Implement a custom parser for chk btree leaves.

The basic parsing is actually quicker (47us to build this new structure vs 110us)
Most likely because we have 1 malloc rather than N per leaf.
Memory size is also much smaller. We'll lose a little bit if we
convert back and forth from keys, etc.

Show diffs side-by-side

added added

removed removed

Lines of Context:
605
605
class _LeafNode(object):
606
606
    """A leaf node for a serialised B+Tree index."""
607
607
 
608
 
    __slots__ = ('keys', 'min_key', 'max_key')
 
608
    __slots__ = ('_keys', 'min_key', 'max_key')
609
609
 
610
610
    def __init__(self, bytes, key_length, ref_list_length):
611
611
        """Parse bytes to create a leaf node object."""
617
617
            self.max_key = key_list[-1][0]
618
618
        else:
619
619
            self.min_key = self.max_key = None
620
 
        self.keys = dict(key_list)
 
620
        self._keys = dict(key_list)
 
621
 
 
622
    def __len__(self):
 
623
        return len(self._keys)
 
624
 
 
625
    def __contains__(self, key):
 
626
        return key in self._keys
 
627
 
 
628
    def __getitem__(self, key):
 
629
        return self._keys[key]
 
630
 
 
631
    def all_items(self):
 
632
        """Return a sorted list of (key, (value, refs)) items"""
 
633
        items = self._keys.items()
 
634
        items.sort()
 
635
        return items
 
636
 
 
637
    def all_keys(self):
 
638
        """Return a sorted list of all keys."""
 
639
        keys = self._keys.keys()
 
640
        keys.sort()
 
641
        return keys
621
642
 
622
643
 
623
644
class _InternalNode(object):
672
693
        self._recommended_pages = self._compute_recommended_pages()
673
694
        self._root_node = None
674
695
        self._base_offset = offset
 
696
        self._leaf_klass = _LeafNode
675
697
        # Default max size is 100,000 leave values
676
698
        self._leaf_value_cache = None # lru_cache.LRUCache(100*1000)
677
699
        if unlimited_cache:
950
972
        """Cache directly from key => value, skipping the btree."""
951
973
        if self._leaf_value_cache is not None:
952
974
            for node in nodes.itervalues():
953
 
                for key, value in node.keys.iteritems():
 
975
                for key, value in node.all_items():
954
976
                    if key in self._leaf_value_cache:
955
977
                        # Don't add the rest of the keys, we've seen this node
956
978
                        # before.
980
1002
        if self._row_offsets[-1] == 1:
981
1003
            # There is only the root node, and we read that via key_count()
982
1004
            if self.node_ref_lists:
983
 
                for key, (value, refs) in sorted(self._root_node.keys.items()):
 
1005
                for key, (value, refs) in self._root_node.all_items():
984
1006
                    yield (self, key, value, refs)
985
1007
            else:
986
 
                for key, (value, refs) in sorted(self._root_node.keys.items()):
 
1008
                for key, (value, refs) in self._root_node.all_items():
987
1009
                    yield (self, key, value)
988
1010
            return
989
1011
        start_of_leaves = self._row_offsets[-2]
999
1021
        # for spilling index builds to disk.
1000
1022
        if self.node_ref_lists:
1001
1023
            for _, node in nodes:
1002
 
                for key, (value, refs) in sorted(node.keys.items()):
 
1024
                for key, (value, refs) in node.all_items():
1003
1025
                    yield (self, key, value, refs)
1004
1026
        else:
1005
1027
            for _, node in nodes:
1006
 
                for key, (value, refs) in sorted(node.keys.items()):
 
1028
                for key, (value, refs) in node.all_items():
1007
1029
                    yield (self, key, value)
1008
1030
 
1009
1031
    @staticmethod
1170
1192
                continue
1171
1193
            node = nodes[node_index]
1172
1194
            for next_sub_key in sub_keys:
1173
 
                if next_sub_key in node.keys:
1174
 
                    value, refs = node.keys[next_sub_key]
 
1195
                if next_sub_key in node:
 
1196
                    value, refs = node[next_sub_key]
1175
1197
                    if self.node_ref_lists:
1176
1198
                        yield (self, next_sub_key, value, refs)
1177
1199
                    else:
1245
1267
            # sub_keys is all of the keys we are looking for that should exist
1246
1268
            # on this page, if they aren't here, then they won't be found
1247
1269
            node = nodes[node_index]
1248
 
            node_keys = node.keys
1249
1270
            parents_to_check = set()
1250
1271
            for next_sub_key in sub_keys:
1251
 
                if next_sub_key not in node_keys:
 
1272
                if next_sub_key not in node:
1252
1273
                    # This one is just not present in the index at all
1253
1274
                    missing_keys.add(next_sub_key)
1254
1275
                else:
1255
 
                    value, refs = node_keys[next_sub_key]
 
1276
                    value, refs = node[next_sub_key]
1256
1277
                    parent_keys = refs[ref_list_num]
1257
1278
                    parent_map[next_sub_key] = parent_keys
1258
1279
                    parents_to_check.update(parent_keys)
1265
1286
            while parents_to_check:
1266
1287
                next_parents_to_check = set()
1267
1288
                for key in parents_to_check:
1268
 
                    if key in node_keys:
1269
 
                        value, refs = node_keys[key]
 
1289
                    if key in node:
 
1290
                        value, refs = node[key]
1270
1291
                        parent_keys = refs[ref_list_num]
1271
1292
                        parent_map[key] = parent_keys
1272
1293
                        next_parents_to_check.update(parent_keys)
1546
1567
                    continue
1547
1568
            bytes = zlib.decompress(data)
1548
1569
            if bytes.startswith(_LEAF_FLAG):
1549
 
                node = _LeafNode(bytes, self._key_length, self.node_ref_lists)
 
1570
                node = self._leaf_klass(bytes, self._key_length,
 
1571
                                        self.node_ref_lists)
1550
1572
            elif bytes.startswith(_INTERNAL_FLAG):
1551
1573
                node = _InternalNode(bytes)
1552
1574
            else: