##// END OF EJS Templates
branchmap: use mmap for faster revbranchcache loading...
Arseniy Alekseyev -
r52268:02e7d79e default
parent child Browse files
Show More
@@ -621,6 +621,74 b' class remotebranchcache(branchcache):'
621 _rbccloseflag = 0x80000000
621 _rbccloseflag = 0x80000000
622
622
623
623
624 class rbcrevs:
625 """a byte string consisting of an immutable prefix followed by a mutable suffix"""
626
627 def __init__(self, revs):
628 self._prefix = revs
629 self._rest = bytearray()
630
631 def __len__(self):
632 return len(self._prefix) + len(self._rest)
633
634 def unpack_record(self, rbcrevidx):
635 if rbcrevidx < len(self._prefix):
636 return unpack_from(_rbcrecfmt, util.buffer(self._prefix), rbcrevidx)
637 else:
638 return unpack_from(
639 _rbcrecfmt,
640 util.buffer(self._rest),
641 rbcrevidx - len(self._prefix),
642 )
643
644 def make_mutable(self):
645 if len(self._prefix) > 0:
646 entirety = bytearray()
647 entirety[:] = self._prefix
648 entirety.extend(self._rest)
649 self._rest = entirety
650 self._prefix = bytearray()
651
652 def truncate(self, pos):
653 self.make_mutable()
654 del self._rest[pos:]
655
656 def pack_into(self, rbcrevidx, node, branchidx):
657 if rbcrevidx < len(self._prefix):
658 self.make_mutable()
659 buf = self._rest
660 start_offset = rbcrevidx - len(self._prefix)
661 end_offset = start_offset + _rbcrecsize
662
663 if len(self._rest) < end_offset:
664 # bytearray doesn't allocate extra space at least in Python 3.7.
665 # When multiple changesets are added in a row, precise resize would
666 # result in quadratic complexity. Overallocate to compensate by
667 # using the classic doubling technique for dynamic arrays instead.
668 # If there was a gap in the map before, less space will be reserved.
669 self._rest.extend(b'\0' * end_offset)
670 return pack_into(
671 _rbcrecfmt,
672 buf,
673 start_offset,
674 node,
675 branchidx,
676 )
677
678 def extend(self, extension):
679 return self._rest.extend(extension)
680
681 def slice(self, begin, end):
682 if begin < len(self._prefix):
683 acc = bytearray()
684 acc[:] = self._prefix[begin:end]
685 acc.extend(
686 self._rest[begin - len(self._prefix) : end - len(self._prefix)]
687 )
688 return acc
689 return self._rest[begin - len(self._prefix) : end - len(self._prefix)]
690
691
624 class revbranchcache:
692 class revbranchcache:
625 """Persistent cache, mapping from revision number to branch name and close.
693 """Persistent cache, mapping from revision number to branch name and close.
626 This is a low level cache, independent of filtering.
694 This is a low level cache, independent of filtering.
@@ -648,7 +716,7 b' class revbranchcache:'
648 assert repo.filtername is None
716 assert repo.filtername is None
649 self._repo = repo
717 self._repo = repo
650 self._names = [] # branch names in local encoding with static index
718 self._names = [] # branch names in local encoding with static index
651 self._rbcrevs = bytearray()
719 self._rbcrevs = rbcrevs(bytearray())
652 self._rbcsnameslen = 0 # length of names read at _rbcsnameslen
720 self._rbcsnameslen = 0 # length of names read at _rbcsnameslen
653 try:
721 try:
654 bndata = repo.cachevfs.read(_rbcnames)
722 bndata = repo.cachevfs.read(_rbcnames)
@@ -664,8 +732,12 b' class revbranchcache:'
664
732
665 if self._names:
733 if self._names:
666 try:
734 try:
667 data = repo.cachevfs.read(_rbcrevs)
735 if repo.ui.configbool(b'format', b'mmap-revbranchcache'):
668 self._rbcrevs[:] = data
736 with repo.cachevfs(_rbcrevs) as fp:
737 data = util.buffer(util.mmapread(fp))
738 else:
739 data = repo.cachevfs.read(_rbcrevs)
740 self._rbcrevs = rbcrevs(data)
669 except (IOError, OSError) as inst:
741 except (IOError, OSError) as inst:
670 repo.ui.debug(
742 repo.ui.debug(
671 b"couldn't read revision branch cache: %s\n"
743 b"couldn't read revision branch cache: %s\n"
@@ -685,7 +757,7 b' class revbranchcache:'
685 del self._names[:]
757 del self._names[:]
686 self._rbcnamescount = 0
758 self._rbcnamescount = 0
687 self._rbcrevslen = len(self._repo.changelog)
759 self._rbcrevslen = len(self._repo.changelog)
688 self._rbcrevs = bytearray(self._rbcrevslen * _rbcrecsize)
760 self._rbcrevs = rbcrevs(bytearray(self._rbcrevslen * _rbcrecsize))
689 util.clearcachedproperty(self, b'_namesreverse')
761 util.clearcachedproperty(self, b'_namesreverse')
690
762
691 @util.propertycache
763 @util.propertycache
@@ -708,9 +780,7 b' class revbranchcache:'
708
780
709 # fast path: extract data from cache, use it if node is matching
781 # fast path: extract data from cache, use it if node is matching
710 reponode = changelog.node(rev)[:_rbcnodelen]
782 reponode = changelog.node(rev)[:_rbcnodelen]
711 cachenode, branchidx = unpack_from(
783 cachenode, branchidx = self._rbcrevs.unpack_record(rbcrevidx)
712 _rbcrecfmt, util.buffer(self._rbcrevs), rbcrevidx
713 )
714 close = bool(branchidx & _rbccloseflag)
784 close = bool(branchidx & _rbccloseflag)
715 if close:
785 if close:
716 branchidx &= _rbcbranchidxmask
786 branchidx &= _rbcbranchidxmask
@@ -733,7 +803,7 b' class revbranchcache:'
733 b"revision branch cache to revision %d\n" % rev
803 b"revision branch cache to revision %d\n" % rev
734 )
804 )
735 truncate = rbcrevidx + _rbcrecsize
805 truncate = rbcrevidx + _rbcrecsize
736 del self._rbcrevs[truncate:]
806 self._rbcrevs.truncate(truncate)
737 self._rbcrevslen = min(self._rbcrevslen, truncate)
807 self._rbcrevslen = min(self._rbcrevslen, truncate)
738
808
739 # fall back to slow path and make sure it will be written to disk
809 # fall back to slow path and make sure it will be written to disk
@@ -782,16 +852,7 b' class revbranchcache:'
782 if rev == nullrev:
852 if rev == nullrev:
783 return
853 return
784 rbcrevidx = rev * _rbcrecsize
854 rbcrevidx = rev * _rbcrecsize
785 requiredsize = rbcrevidx + _rbcrecsize
855 self._rbcrevs.pack_into(rbcrevidx, node, branchidx)
786 rbccur = len(self._rbcrevs)
787 if rbccur < requiredsize:
788 # bytearray doesn't allocate extra space at least in Python 3.7.
789 # When multiple changesets are added in a row, precise resize would
790 # result in quadratic complexity. Overallocate to compensate by
791 # use the classic doubling technique for dynamic arrays instead.
792 # If there was a gap in the map before, less space will be reserved.
793 self._rbcrevs.extend(b'\0' * max(_rbcmininc, requiredsize))
794 pack_into(_rbcrecfmt, self._rbcrevs, rbcrevidx, node, branchidx)
795 self._rbcrevslen = min(self._rbcrevslen, rev)
856 self._rbcrevslen = min(self._rbcrevslen, rev)
796
857
797 tr = self._repo.currenttransaction()
858 tr = self._repo.currenttransaction()
@@ -866,5 +927,5 b' class revbranchcache:'
866 f.seek(start)
927 f.seek(start)
867 f.truncate()
928 f.truncate()
868 end = revs * _rbcrecsize
929 end = revs * _rbcrecsize
869 f.write(self._rbcrevs[start:end])
930 f.write(self._rbcrevs.slice(start, end))
870 self._rbcrevslen = revs
931 self._rbcrevslen = revs
@@ -2913,3 +2913,8 b' section = "blackbox"'
2913 name = "date-format"
2913 name = "date-format"
2914 default = ""
2914 default = ""
2915 in_core_extension = "blackbox"
2915 in_core_extension = "blackbox"
2916
2917 [[items]]
2918 section = "format"
2919 name = "mmap-revbranchcache"
2920 default = false
@@ -1,3 +1,12 b''
1 #testcases mmap nommap
2
3 #if mmap
4 $ cat <<EOF >> $HGRCPATH
5 > [format]
6 > mmap-revbranchcache=true
7 > EOF
8 #endif
9
1 $ hg init a
10 $ hg init a
2 $ cd a
11 $ cd a
3
12
@@ -921,17 +930,10 b' Test that cache files are created and gr'
921 $ f --size --hexdump .hg/cache/rbc-*
930 $ f --size --hexdump .hg/cache/rbc-*
922 .hg/cache/rbc-names-v1: size=1
931 .hg/cache/rbc-names-v1: size=1
923 0000: 61 |a|
932 0000: 61 |a|
924 .hg/cache/rbc-revs-v1: size=152
933 .hg/cache/rbc-revs-v1: size=48
925 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
934 0000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
926 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
935 0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
927 0020: 00 00 00 00 00 00 00 00 d8 cb c6 1d 00 00 00 00 |................|
936 0020: 00 00 00 00 00 00 00 00 d8 cb c6 1d 00 00 00 00 |................|
928 0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
929 0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
930 0050: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
931 0060: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
932 0070: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
933 0080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
934 0090: 00 00 00 00 00 00 00 00 |........|
935
937
936 $ cd ..
938 $ cd ..
937
939
General Comments 0
You need to be logged in to leave comments. Login now